git rebase -i -autosquash 冲突

Joh*_*uhh 5 git conflict fixup

git 在使用 --fixup 和 --autosquash 时让我很头疼。我想举两个例子,一个工作得很好,另一个是一团糟。(git 版本 2.6.2)

工作示例:

第一次提交:

$ git init
$ printf '1\n' > test.file
$ git add test.file
$ git commit -m 'Insert 1 --> first line'  
$ cat test.file
1
Run Code Online (Sandbox Code Playgroud)

第二次提交(BUG):

$ printf 'This is\na BUG\n' >> test.file
$ git commit -am 'Added line 2 and 3 with BUG'
$ cat test.file
1  
This is  
a BUG
Run Code Online (Sandbox Code Playgroud)

第三次提交:

$ sed -i '2i 2' test.file
$ git commit -am 'Insert 2 --> second line'
$ cat test.file
1  
2  
This is  
a BUG
Run Code Online (Sandbox Code Playgroud)

第四次提交(修复):

$ sed -i 's/a BUG/NOT a BUG/' test.file
$ git add test.file
$ git log --oneline
b021696 Insert 2 --> second line  
2e18b8d Added line 2 and 3 with BUG  
d7b60a1 Insert 1 --> first line  
$ git commit --fixup HEAD~
$ cat test.file
1  
2  
This is  
NOT a BUG
Run Code Online (Sandbox Code Playgroud)

变基:

$ git log --oneline
fe99989 fixup! Added line 2 and 3 with BUG  
b021696 Insert 2 --> second line  
2e18b8d Added line 2 and 3 with BUG  
d7b60a1 Insert 1 --> first line

$ git rebase -i --autosquash HEAD~3

[detached HEAD 6660b0e] Added line 2 and 3 with BUG
Date: Tue Nov 3 13:28:07 2015 +0100
1 file changed, 2 insertions(+)
Successfully rebased and updated refs/heads/master.
Run Code Online (Sandbox Code Playgroud)

头痛的例子:(唯一的区别是BUGGY提交是一行)

第一次提交:

$ git init
$ printf '1\n' > test.file
$ git add test.file
$ git commit -m 'Insert 1 --> first line'  
$ cat test.file
1
Run Code Online (Sandbox Code Playgroud)

第二次提交(BUG):

$ printf 'This is a BUG\n' >> test.file
$ git commit -am 'Added line 2 with BUG'
$ cat test.file
1
This is a BUG
Run Code Online (Sandbox Code Playgroud)

第三次提交:

$ sed -i '2i 2' test.file
$ git commit -am 'Insert 2 --> second line'
$ cat test.file
1  
2  
This is a BUG
Run Code Online (Sandbox Code Playgroud)

第四次提交(修复):

$ sed -i 's/a BUG/NOT a BUG/' test.file
$ git add test.file
$ git log --oneline
2b83fe7 Insert 2 --> second line  
62cdd05 Added line 2 with BUG  
0ee3343 Insert 1 --> first line
$ git commit --fixup HEAD~
$ cat test.file
1  
2  
This is NOT a BUG
Run Code Online (Sandbox Code Playgroud)

变基:

$ git log --oneline
c3d3db7 fixup! Added line 2 with BUG  
2b83fe7 Insert 2 --> second line  
62cdd05 Added line 2 with BUG  
0ee3343 Insert 1 --> first line
$ git rebase -i --autosquash HEAD~3
error: could not apply c3d3db7... fixup! Added line 2 with BUG

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 c3d3db78440e48c1bb637f78e0767520db65ea1e... fixup! Added line 2 with BUG

$ git status
interactive rebase in progress; onto 0ee3343
Last commands done (2 commands done):
   pick 62cdd05 Added line 2 with BUG
   fixup c3d3db7 fixup! Added line 2 with BUG
Next command to do (1 remaining command):
   pick 2b83fe7 Insert 2 --> second line
  (use "git rebase --edit-todo" to view and edit)
You are currently rebasing branch 'master' on '0ee3343'.
  (fix conflicts and then run "git rebase --continue")
  (use "git rebase --skip" to skip this patch)
  (use "git rebase --abort" to check out the original branch)

Unmerged paths:
  (use "git reset HEAD <file>..." to unstage)
  (use "git add <file>..." to mark resolution)

        both modified:   test.file

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

$ cat test.file
1 
<<<<<<< HEAD
This is a BUG
======= 
2 
This is NOT a BUG
>>>>>>> c3d3db7... fixup! Added line 2 with BUG
Run Code Online (Sandbox Code Playgroud)

为什么修复不能干净地应用?

为什么 fixup 还包含“2”,它不应该在 fixup 引入的补丁中,而是在前一次提交的补丁中。

Mad*_*ist 4

当您执行 a 时--fixup,您正在无序地应用补丁,因此上下文消失了。在第一种情况下,您的补丁将按如下方式应用:

  1. 1在第 1 行插入
  2. This is\naBUG在第 2、3 行之后插入1
  3. 删除a BUG第 4 行之后的第 行This is,替换为NOT a BUG
  4. 2在第 2 行之后1、之前插入This is

步骤 2、3 非常明确。即使行号与步骤 3 中的预期不同,上下文也很清楚。在第二种情况下,

  1. 1在第 1 行插入
  2. This is a BUG在第 2 行之后插入1
  3. 删除行This is a BUG,替换为This is NOT a BUG第3行之后的行2
  4. 2在第 2 行之后、1之前插入This is a BUG

在这种情况下,补丁 #3 是不可能的,因为This is a BUG它不会出现在第 3 行以及它之前的行上2。在本例中,由于缺少上下文,Git 并不认为第 2 行是正确的。

解决此问题的最简单方法是重新排列变基顺序以反映您实际在做什么。而不是原来的顺序:

pick 5ef0459 Added line 2 with BUG
fixup ed5cd81 fixup! Added line 2 with BUG
pick 20e104e Insert 2 --> second line
Run Code Online (Sandbox Code Playgroud)

切换最后两个元素以为补丁提供所需的上下文:

pick 5ef0459 Added line 2 with BUG
pick 20e104e Insert 2 --> second line
fixup ed5cd81 fixup! Added line 2 with BUG
Run Code Online (Sandbox Code Playgroud)

在这种情况下,您可能需要将-k标志添加到命令行以保留最后一次提交,该提交基本上是空的:

$ git rebase -i -k --autosquash HEAD~3
 Date: Tue Nov 3 10:45:40 2015 -0500
 1 file changed, 2 insertions(+), 1 deletion(-)
Successfully rebased and updated refs/heads/master.
$ cat test
1
2
This is NOT a BUG
Run Code Online (Sandbox Code Playgroud)

另一种选择当然是在变基失败时按照提示手动使用git merge或修复冲突。git mergetool

-s recursive -X theirs您可以通过添加或-s recursive -X ours指定策略来​​使变基“成功” 。然而,由于上下文冲突,在这两种情况下您的修复都会被破坏。