git pull --rebase在同事的git push -force

时间:2017-03-01 16:28:43

标签: git version-control rebase

我以为我理解git pull -rebase是如何工作的,但这个例子令我感到困惑。我猜想以下两种情况会产生相同的结果,但它们不同。

首先,有效的那个。

# Dan and Brian start out at the same spot:
dan$ git rev-parse HEAD
067ab5e29670208e654c7cb00abf3de40ddcc556

brian$ git rev-parse HEAD
067ab5e29670208e654c7cb00abf3de40ddcc556

# Separately, each makes a commit (different files, no conflict)
dan$ echo 'bagels' >> favorite_foods.txt
dan$ git commit -am "Add bagels to favorite_foods.txt"

brian$ echo 'root beer' >> favorite_beverages.txt
brian$ git commit -am "I love root beer"

# Brian pushes first, then Dan runs `git pull --rebase`
brian$ git push

dan$ git pull --rebase
dan$ git log
commit 9e1140410af8f2c06f0188f2da16335ff3a6d04c
Author: Daniel
Date:   Wed Mar 1 09:31:41 2017 -0600

    Add bagels to favorite_foods.txt

commit 2f25b9a25923bc608b7fba3b4e66de9e97738763
Author: Brian
Date:   Wed Mar 1 09:47:09 2017 -0600

    I love root beer

commit 067ab5e29670208e654c7cb00abf3de40ddcc556
Author: Brian
Date:   Wed Mar 1 09:27:09 2017 -0600

    Shared history

所以这很好。在另一个场景中,想象Dan推动,然后Brian(粗鲁地)推动 - 强迫他的承诺。现在,当Dan运行git pull --rebase时,他的提交已经消失。

# Dan and Brian start out at the same spot:
dan$ git rev-parse HEAD
067ab5e29670208e654c7cb00abf3de40ddcc556

brian$ git rev-parse HEAD
067ab5e29670208e654c7cb00abf3de40ddcc556

# Separately, each makes a commit (different files, no conflict)
dan$ echo 'bagels' >> favorite_foods.txt
dan$ git commit -am "Add bagels to favorite_foods.txt"

brian$ echo 'root beer' >> favorite_beverages.txt
brian$ git commit -am "I love root beer"

# THIS TIME, Dan pushes first, then Brian force pushes.
dan$ git push

brian$ git push --force

dan$ git pull --rebase
dan$ git log  # Notice, Dan's commit is gone!
commit 2f25b9a25923bc608b7fba3b4e66de9e97738763
Author: Brian
Date:   Wed Mar 1 09:47:09 2017 -0600

    I love root beer

commit 067ab5e29670208e654c7cb00abf3de40ddcc556
Author: Brian
Date:   Wed Mar 1 09:27:09 2017 -0600

    Shared history

分支的原始版本在Brian push --force之后与第一个场景中的状态相同,所以我期望git pull --rebase的行为相同。我很困惑为什么丹的承诺丢失了。

我理解pull --rebase说“接受我的本地更改,并在远程更改后应用它们”。我不认为局部的变化会被抛弃。此外,如果Dan已经运行git pull(没有--rebase),他的提交也不会丢失。

那么为什么丹跑git pull --rebase时失去了他的本地提交?强制推动对我来说很有意义,但是不应该让遥控器处于和Brian先推动一样的状态吗?

我怎么想这个错误?

4 个答案:

答案 0 :(得分:1)

解决办法如下:

git reflog

在那里挖掘以找到丢失的提交 SHA。然后……

git cherry-pick <SHA-of-the-commit-you-found>

答案 1 :(得分:0)

这两种情况都不会让人感到困惑,这就是null的工作方式。

我不会解释第一个场景,因为你也明白这一点。但是在push --force这种情况发生的第二种情况下,布莱恩的本地存储库并不知道有什么关于丹的推动。

因此需要brian的本地副本&amp;替换遥控器中的所有内容,因为它是brian$ git push --force

force push&amp;之间的差异git pull是,

git pull --rebase会比较来源和变化的变化本地。这就是为什么即使你有git pull的未完成的更改。

git pull不会将更改与本地进行比较,但它会从原点获取所有内容。这就是为什么如果有不明智的变化你就不能git pull --rebase

希望你明白我说的话。 有问题吗?

答案 2 :(得分:0)

是的,这看起来是正确的。 Brian的git push --force将最新的提交设置为他在本地系统上的提交。如果Brian首先提取任何最新提交然后git push --force,结果将是相同的。

这是一个包含更多信息的好帖子:Force "git push" to overwrite remote files

答案 3 :(得分:0)

是的,您对git pull --rebase的理解是正确的。

这是因为提交9e11404已推送到远程,而在此之后,提交2f25b9a强制更新远程(9e11404,如果强制从远程删除)。

当Dan执行git pull --rebase时,git检测到9e11404,而origin / branch指向2f25b9a。但是git认为9e11404已经存在于远程(.git\logs\refs\remotes\origin\branch具有内容update by push 9e1140410af8f2c06f0188f2da16335ff3a6d04c),所以它不会对rebase做任何事情。或者您可以使用git pull --rebase=interactive进行验证,您会发现它会显示noop以进行重新定位。如果您想在origin / branch的顶部手动重新定位9e11404,可以在交互式窗口中添加pick 9e11404,结果将是您的预期。