我正在学习 Git rebase :
我创建了一个冲突情况来测试
git rebase -i
命令的行为。
我git rebase --skip
当参与的冲突发生时,最后:没有数据丢失,
--skip
做了什么?
这里是我创建来测试的冲突情况:
[code]
git add .
-> 新提交:“feature”,一切正常。[code]
[feature]
git add .
-> 新提交:“skip”.[code]
[feature]
skip
git add .
-> 新提交:“new feature”。[code]
[feature]
skip
[new feature]
情况已定。
我现在用
git rebase -i HEAD~4
启动变基测试,pick 9fc9fbd save
pick 036ad6a skip
pick da647db feature
pick 8763ea1 new feature
走吧,冲突来了:
Auto-merging git-modif-annulation.md
CONFLICT (content): Merge conflict in git-modif-annulation.md
error: could not apply 036ad6a... skip
hint: Resolve all conflicts manually, mark them as resolved with
hint: "git add/rm <conflicted_files>", then run "git rebase --continue".
hint: You can instead skip this commit: run "git rebase --skip".
hint: To abort and get back to the state before "git rebase", run "git rebase --abort".
Could not apply 036ad6a... skip
所以我
git rebase --skip
如预期的那样:没想到 :
“新功能”的新冲突:
<<<<<<< HEAD
=======
skip
[new feature]
>>>>>>> new feature
[new feature]
应该在这里,但为什么skip
是?
这让我重新思考我对 Git 工作方式的了解:
我以为只有更改以增量方式保存在提交中。
但是,如果
skip
出现在“new feature”中,是否意味着每次提交都是对项目的一个新的完整保存?或者也许只是文件?
无论如何:跳过“skip”没有效果。
但是 GitHub 文档关于这个 说它应该:
你可以运行
来完全跳过提交。 这意味着不会包含有问题的提交引入的任何更改.git rebase --skip
我错过了什么?
我尝试放弃“skip”提交:相同的结果。
pick 9fc9fbd save
pick da647db feature
drop 036ad6a skip
pick 8763ea1 new feature
删除“skip”提交在应用下一个提交时生成相同的冲突:
“skip”带来的所有修改都由下一次commit带来...
这是樱桃采摘效果(注意:
git rebase
是对一系列单独的樱桃采摘进行批处理的一种方法)。
当您挑选一个提交时,
git
求助于三向合并,但使用现有提交未表示的合并基础。
让我试着说明一下:
# starting point:
* (HEAD -> master) master head commit
| * (feature) c2 - feature head commit
| * c1
| * p
| |
|/
*
*
...
如果你目前在
master
,然后运行git cherry-pick c1
:
git 将解决 3 路合并,使用 :
HEAD
作为“我们的”c1
作为“他们的”p
作为基础 (<- that's the changing point)就好像它正在解决以下合并:
* (HEAD -> master) master head commit
| * c1
\|
* p
$ git merge c1
因此,您在“我们的”方面看到的 diff 是
p
和 HEAD
之间的差异——尽管 p
和 HEAD
在提交顺序中并不直接相关。
现在假设您挑选了两个提交:
git cherry-pick c1 c2
(注意:这与git rebase --onto master p c2
相同)
出于某种原因(冲突......)你决定跳过
c1
.git cherry-pick c2
),三向差异的“我们的”一侧将是c1
和master
之间的差异。
所以,即使你没有把
c1
放在master之上,呈现给你的diff仍然和c1
的内容有关。
回到你的例子:
c1
会是skip
,c2
会是new feature
.
即使您跳过了
c1
,当您尝试挑选c2
时,git仍然会尝试调和“跳过'行已删除”(git diff skip *master+save+feature*
)与“在行'之后添加'新功能'”的差异跳过'”(git diff skip new_feature
).更一般地说,这就是为什么在进行变基时,您可能会一遍又一遍地解决相同的冲突:
n
,n+1
时,你仍然会有一个差异,它没有反映出第一个解决方案。有一个 git 功能可以缓解这个问题:
git rerere
-- “Reuse recorded resolution”的首字母缩写词
启用它:
git config --global rerere.enabled true
它以某种方式存储您为冲突提供的解决方案,并且当它再次识别出相同的冲突时,重新应用相同的解决方案。
git help rerere
。