gitでconflictした時のours/theirs

git merge/rebaseでconflictした時、`git checkout --ours/--theirs` が何を指しているのかを整理する。

# 準備

```bash
mkdir test
cd test
git init

touch file
git add file
git commit -am 'init'

git checkout -b alice master
echo 'alice 1' >> file
git commit -am 'alice 1'
echo 'alice 2' >> file
git commit -am 'alice 2'
echo 'alice 3' >> file
git commit -am 'alice 3'

git checkout -b bob master
echo 'bob 1' >> file
git commit -am 'bob 1'
echo 'bob 2' >> file
git commit -am 'bob 2'
echo 'bob 3' >> file
git commit -am 'bob 3'
```

次のようなツリーになるので、ここから色々操作してみる。

```
* <49acc5b> [TTouka]  (HEAD, bob) bob 3
* <a3bce11> [TTouka]  bob 2
* <971d689> [TTouka]  bob 1
| * <1596bc6> [TTouka]  (alice) alice 3
| * <4c13261> [TTouka]  alice 2
| * <e361716> [TTouka]  alice 1
|/
* <93ce8a8> [TTouka]  (master) init
```

# 例

## merge

```bash
git checkout -b m-alice-bob alice
git merge bob
# Auto-merging file
# CONFLICT (content): Merge conflict in file
# Automatic merge failed; fix conflicts and then commit the result.
```

```diff
<<<<<<< HEAD
alice 1
alice 2
alice 3
=======
bob 1
bob 2
bob 3
>>>>>>> bob
```

* ours: m-alice-bob
* theirs: bob

m-alice-bobがbobをmergeするので、 *Branch 'm-alice-bob' merges branch 'bob' into itself* となる。

### ours

```bash
git checkout --ours file
```

```diff
alice 1
alice 2
alice 3
```

### theirs

```bash
git checkout --theirs file
```

```diff
bob 1
bob 2
bob 3
```

## rebase

```bash
git checkout -b r-alice-bob alice
git rebase bob
# First, rewinding head to replay your work on top of it...
# Applying: alice 1
# Using index info to reconstruct a base tree...
# M	file
# Falling back to patching base and 3-way merge...
# Auto-merging file
# CONFLICT (content): Merge conflict in file
# Failed to merge in the changes.
# Patch failed at 0001 alice 1
# The copy of the patch that failed is found in:
#    /Users/TTouka/test/.git/rebase-apply/patch
# 
# When you have resolved this problem, run "git rebase --continue".
# If you prefer to skip this patch, run "git rebase --skip" instead.
# To check out the original branch and stop rebasing, run "git rebase --abort".
```

* ours: bobの先頭
* theirs: r-alice-bobのcommit

まずbobの先頭commitをcheckoutし、r−alice-bobのcommitを順番にmergeしていくので、 *HEAD merges branch 'r-alice-bob' into itself* となる。

### ours

```bash
git checkout --ours file
```

```diff
bob 1
bob 2
bob 3
```

### theirs

```bash
git checkout --theirs file
```

```diff
alice 1
```

## git merge後のgit rebase -i

この記事の主目的。このパターンで混乱している人が目の前にいたので、整理してみる。

たとえば、先のmergeで発生したconflictを次のように修正してcommitする:

```text
alice 1
bob 1
alice 2
bob 2
alice 3
bob 3
```

```text
*   <a5e4462>  [TTouka]  (HEAD, m-alice-bob) Merge branch 'bob' into m-alice-bob
|\
| * <49acc5b>  [TTouka]  (bob) bob 3
| * <a3bce11>  [TTouka]  bob 2
| * <971d689>  [TTouka]  bob 1
* | <1596bc6>  [TTouka]  (alice) alice 3
* | <4c13261>  [TTouka]  alice 2
* | <e361716>  [TTouka]  alice 1
|/
* <93ce8a8>  [TTouka]  (master) init
```

ここから `git rebase -i` でsquashしてみる:

```bash
git checkout -b s-alice-bob m-alice-bob
git rebase -i HEAD~1
```

```text
pick 971d689 bob 1
pick a3bce11 bob 2
pick 49acc5b bob 3
```

`HEAD~1` という指定に対し、3つのcommitが表示された。
(merge commitの中身 (bob 1からbob 3) が1段階としてカウントされている。)

ここで、bob 2とbob 3をbob 1にsquashしてみる:

```text
pick 971d689 bob 1
s a3bce11 bob 2
s 49acc5b bob 3

(save)

error: could not apply 971d689... bob 1

When you have resolved this problem, run "git rebase --continue".
If you prefer to skip this patch, run "git rebase --skip" instead.
To check out the original branch and stop rebasing, run "git rebase --abort".
Could not apply 971d689c3a8f3130660a22a8c4cbb46097eb4bdb... bob 1
```

```text
*   <a5e4462>  [TTouka]  (s-alice-bob, m-alice-bob) Merge branch 'bob' into m-alice-bob
|\
| * <49acc5b>  [TTouka]  (bob) bob 3
| * <a3bce11>  [TTouka]  bob 2
| * <971d689>  [TTouka]  bob 1
* | <1596bc6>  [TTouka]  (HEAD, alice) alice 3
* | <4c13261>  [TTouka]  alice 2
* | <e361716>  [TTouka]  alice 1
|/
* <93ce8a8>  [TTouka]  (master) init
```

s-alice-bobに属するコミットとしてbob 1からbob 3をrebaseするので、まずalice 3にbob 1が後続するためのrebaseが実行される。

*Commit 'alice 3' merges commit 'bob 1' into itself* なので

* ours: alice 3
* theirs: bob 1

conflictを修正し `git rebase --continue` する

```text
* <163a666> [TTouka]  (HEAD) bob 1
| *   <a5e4462> [TTouka]  (s-alice-bob, m-alice-bob) Merge branch 'bob' into m-alice-bob
| |\
|/ /
| * <49acc5b> [TTouka]  (bob) bob 3
| * <a3bce11> [TTouka]  bob 2
| * <971d689> [TTouka]  bob 1
* | <1596bc6> [TTouka]  (alice) alice 3
* | <4c13261> [TTouka]  alice 2
* | <e361716> [TTouka]  alice 1
|/
* <93ce8a8> [TTouka]  (master) init
```

順次修正、continueする

```text
* <af8b869> [TTouka]  (HEAD) bob 1 and bob 2
| *   <a5e4462> [TTouka]  (s-alice-bob, m-alice-bob) Merge branch 'bob' into m-alice-bob
| |\
|/ /
| * <49acc5b> [TTouka]  (bob) bob 3
| * <a3bce11> [TTouka]  bob 2
| * <971d689> [TTouka]  bob 1
* | <1596bc6> [TTouka]  (alice) alice 3
* | <4c13261> [TTouka]  alice 2
* | <e361716> [TTouka]  alice 1
|/
* <93ce8a8> [TTouka]  (master) init
```

最終的にこうなる。

```text
* <4eb944c> [TTouka]  (HEAD, s-alice-bob) bob 1, bob 2, and bob 3
| *   <a5e4462> [TTouka]  (m-alice-bob) Merge branch 'bob' into m-alice-bob
| |\
|/ /
| * <49acc5b> [TTouka]  (bob) bob 3
| * <a3bce11> [TTouka]  bob 2
| * <971d689> [TTouka]  bob 1
* | <1596bc6> [TTouka]  (alice) alice 3
* | <4c13261> [TTouka]  alice 2
* | <e361716> [TTouka]  alice 1
|/
* <93ce8a8> [TTouka]  (master) init
```

# まとめ

merge/rebaseいずれの場合も *A merges B into itself* ととらえれば、

* ours: A (主語)
* theirs: B (目的語)

となって混乱しないと思う。