我以为我理解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先推动一样的状态吗?
我怎么想这个错误?
答案 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
,结果将是您的预期。