【git】git でコンフリクトさせて解消してみる


git のおそらく最初の壁であるコンフリクトしたときの対応。

リポジトリを用意する。リポジトリの中身は↓

```
.
├── README.md
└── conflict.txt
```

コンフリクトさせるために、2つローカルにクローンする。
https://github.com/kiyo27/git-practice

```bash
> git clone git@github.com:kiyo27/git-practice.git repo-a
> git clone git@github.com:kiyo27/git-practice.git repo-b
```

repo-aのファイルを編集してリモートにプッシュする

```bash
> cd repo-a
> echo "hello world v1." > conflict.txt
```

変更をリモートに変更する

```bash
> git commit -am "hello world v1"
> git push origin main
```

repo-bでファイルを編集する

```bash
> cd repo-b
> echo "hello world v2 > conflict.txt
```

変更をコミットする

```bash
> git -am "hello world v2
```

リモートプッシュしてみる

```bash
> git push origin main
> git push origin main
To github.com:kiyo27/git-practice.git
 ! [rejected]        main -> main (fetch first)
error: failed to push some refs to 'git@github.com:kiyo27/git-practice.git'
hint: Updates were rejected because the remote contains work that you do
hint: not have locally. This is usually caused by another repository pushing
hint: to the same ref. You may want to first integrate the remote changes
hint: (e.g., 'git pull ...') before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.
```

``git pull``すると、コンフリクト発生する。

```bash
> git pull origin main
remote: Enumerating objects: 9, done.
remote: Counting objects: 100% (9/9), done.
remote: Compressing objects: 100% (4/4), done.
remote: Total 6 (delta 1), reused 6 (delta 1), pack-reused 0
Unpacking objects: 100% (6/6), 718 bytes | 12.00 KiB/s, done.
From github.com:kiyo27/git-practice
 * branch            main       -> FETCH_HEAD
   bd537dc..27be7d3  main       -> origin/main
Auto-merging conflict.txt
CONFLICT (content): Merge conflict in conflict.txt
Automatic merge failed; fix conflicts and then commit the result.
```

``conflict.txt``はマージされていない状態

```bash
> git status
On branch main
Your branch and 'origin/main' have diverged,
and have 1 and 1 different commits each, respectively.
  (use "git pull" to merge the remote branch into yours)

You have unmerged paths.
  (fix conflicts and run "git commit")
  (use "git merge --abort" to abort the merge)

Unmerged paths:
  (use "git add <file>..." to mark resolution)
        both modified:   conflict.txt

no changes added to commit (use "git add" and/or "git commit -a")
```

コンフリクトしたファイルの中身

```bash
> cat conflict.txt
<<<<<<< HEAD
hello world v2
=======
hello world v1.
>>>>>>> 940a9ee69fb3fe10f55c32d4beb01c5a604f2bc4
```

HEADが何を指しているのか確認します。まずは履歴の確認

```bash
// repo-bで作業
> git log --oneline
8aee435 (HEAD -> main) hello world v2
```
``HEAD``は``main``ブランチの先頭を指しています。

``940a9ee69fb3fe10f55c32d4beb01c5a604f2bc4``が何を指しているかを確認します。

```bash
> git log --oneline --no-abbrev-commit --all
8aee435f11c3b1e3840162816fb4702cbf6c1fa6 (HEAD -> main) hello world v2
940a9ee69fb3fe10f55c32d4beb01c5a604f2bc4 (origin/main, origin/HEAD) hello world v1.
```

``940a9ee69fb3fe10f55c32d4beb01c5a604f2bc4``はリモートの``main``ブランチを指しています（repe-aの変更）。

repo-bでの変更を適用する。

```text:conflict.txt
<<<<<<< HEAD ← 消す
hello world v2
======= ← 消す
hello world v1. ← 消す
>>>>>>> 940a9ee69fb3fe10f55c32d4beb01c5a604f2bc4 ← 消す
```

修正後

```conflict.txt
hello world v2
```

コミットする

```bash
> git add conflict.txt
> git commit
> git status
On branch main
Your branch is ahead of 'origin/main' by 2 commits.
  (use "git push" to publish your local commits)

nothing to commit, working tree clean
> git log --oneline
c43cfe1 (HEAD -> main) Merge branch 'main' of github.com:kiyo27/git-practice into main
8aee435 hello world v2
940a9ee (origin/main, origin/HEAD) hello world v1.
```

コンフリクト解消したので、リモートにプッシュする。

```bash
> git push origin main
```