`git rebase --skip` 但仍然包含更改

问题描述 投票:0回答:1

我正在学习 Git rebase :
我创建了一个冲突情况来测试

git rebase -i
命令的行为。 我
git rebase --skip
当参与的冲突发生时,
但是之后发生了另一个冲突,并且“跳过”的数据重新出现在另一个提交中。

最后:没有数据丢失,

--skip
做了什么?

这里是我创建来测试的冲突情况:

  • 我将当前代码保存在提交中:“saved
[code]
  • 我添加一个功能 -> ctrl + s ->
    git add .
    -> 新提交:“feature”,一切正常。
[code]
[feature]
  • 我会跳过一些测试 -> ctrl + s ->
    git add .
    -> 新提交:“skip”.
[code]
[feature]
skip
  • 最后是 -> ctrl + s ->
    git add .
    -> 新提交:“new feature”。
[code]
[feature]
skip
[new feature]

情况已定。

我现在用

git rebase -i HEAD~4
启动变基测试,
并向上移动“skip”提交(在“feature”之前),以产生冲突。

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
如预期的那样:
-> "skip" 被跳过,
-> 应用“feature”,
和...

没想到 :
新功能”的新冲突:

<<<<<<< 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 version-control rebase
1个回答
1
投票

这是樱桃采摘效果(注意:

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

© www.soinside.com 2019 - 2024. All rights reserved.