git fetch,git rebase和git pull –rebase有什么区别?

在阅读git pull页面,它给了这个关于git pull --rebase严厉警告:

这是一种潜在的危险操作模式。 它重写历史,当你发布历史时,这并不是一个好兆头。 除非你仔细阅读了git-rebase(1),否则不要使用这个选项。

git rebase页面中,它提供了很多描述,但没有这种警告。

另外,我见过一些人这样说

 git fetch git rebase 

是相同的

 git pull --rebase 

而其他人则说他们有些不同。

什么是真相?

使用git的规则是,你不应该试图在共享/发布/推送后改变历史。 当然,如果你真的想要拥有足够的权限,你可以这样做,但是应该非常小心,因为这会让其他人陷入困境。

现在幸运的是,当你有一个典型的git部署,只有一个上游存储库(origin),它是宇宙中所有优秀和真实的源代码的时候,你可以使用git pull --rebase来处理你的内容,这将是完全安全的在我看来,给你一个更加理智(意义上线性)的历史。 我和我的团队不断使用它。

然而,如果你开始有多个遥控器,并开始做git pull --rebase <arguments>这样你就不再每次都要重定义同一个目标,或者开始推动你的分支到备用版本库之前运行git pull --rebase主要上游 – 那么你可以开始遇到麻烦。 任何时候,如果你与另一个远程/存储库共享你的改变,然后改变这些改变(即使提交信息/内容没有改变,改变的值等于改变SHA /父/等等),你可以把那些有旧的改变。

只要你不脱离rebase理智的信封, git pull --rebase将会对你非常有利。

那么,错误,不会回答关于git pull --rebasegit fetch && git rebase @{u}之间的区别的问题我会继续说,我不知道任何区别,如果有一个,这是微妙的,我没有注意到在我使用git的年份。 可能的话,系统会计算出分支机构应该提取的正确的存储库,如果您有多个存储库并且“origin”不是该分支的上游?

即使你用git-rebase进行非常错误的操作,你当然可以用git log -g和/或git reset --hard ORIG_HEAD轻松地恢复到原始的预先rebase环境。 只是不要做推力(几乎所有的git服务器默认都不允许),你会很高兴。

EDITED

随着时间的stream逝,我的理解已经扩大 git pull --rebasegit rebase叫做rebase工作,所以在这个意义上它们之间没有区别。 但是,git-pull实际上调用了git rebase --onto @{u} $(git merge-base HEAD @{u}@{1}) OK,那个语法(“@ {u} @ {1}”)有点不透明,是一个简单的引导,但重点是,它发现什么合并基地是上游之前,它运行fetch命令。 这有什么不同,你问? 那么,在正常情况下没有。 但是,如果您正在改变上游指向的位置,或者上游本身已经重新设置,那就相当多了。 如果上游被重写,然后你做了一个git rebase @{u}你可能会非常不高兴,可能会得到双重提交或冲突,这取决于旧的提交被重写了多less。 但是,只有你自己和你自己的提交将被应用在@ {u}的顶端,这是git pull --rebase背后的魔力。

好的,这也是一个简化。 如果上游在100次提交之前进行了重新分配(但实际上有101次以上的提交), 并且在进行git pull --rebase 之前做了一次git fetch 那么git将无法准确地确定正确的历史合并基地是要弄清楚你的本地提交是什么。 其结果是, git fetch被认为是有害的(当你有本地的提交和上游被重写)。 然而,真正的经验法则是“从未尝试改变历史被共享/发布/推送后”这是我开始的地方。

TL; DR:

git fetch被认为是有害的(所以使用git pull --rebase ); 并且不会在共享/发布/推送后尝试更改历史logging(因为除此之外,这会导致git fetch有害)。

事实是,他们不同的。 这是一个非常有用的网页,可以很好地解释它:

http://gitolite.com/git-pull–rebase.html

所以git pull --rebasegit fetch; git rebase有一些重要的魔法git fetch; git rebase 大部分时间你都不会注意到git fetch; git rebase ,但是如果上游维护者轻率地忽略了所有那些严厉的警告,并决定重写公共分支的历史,那么通过咨询当地的reflog和做以更聪明的方式在当地重build。

这就是说,这仍然是一个rebase,所以你仍然在重写历史! 因此,所有标准的严重警告仍然适用。 但是,如果你正在一个私人的(即未发表的)分支上工作,那就没问题。

关于严厉的警告我会多说一点。 他们是有效的,但个人而言,我发现大多数人对rebase的偏执有点偏执,就像git rebase在半夜爬到他们的卧室里,当他们年轻时,吃了他们的姐姐或什么东西。 真的不该那么吓人:

  • 如果它是一个私人的分支,重新定义你心中的内容
  • 如果是公共部门,除非你真的必须这样做,否则不要重新分配资金,如果你这样做的话,确保你了解这个影响,并确保任何可能受到影响的人都知道你做了什么,所以他们不得到一个令人讨厌的惊喜,并浪费大量的时间来搞清楚发生了什么。

就这么简单。 是的,我会尽可能积极地鼓励人们定期在他们的私人分支上进行git rebase -i 。 在推送到公共/上游之前的抛光历史是一件好事 ,因为没有人愿意通过一个项目的历史,这个历史充满了'哎呀,修正了我犯了3个犯下的错误'的提交。 (OTOH,不要完全沉迷于追求完美的历史,我们是人,我们犯错误,处理它)

最后一个关于git pull --rebase magic的观察。 如果上游公共分支机构以合理的方式进行了改造(例如压缩/修改提交,或者放弃不应该提交的提交),那么这个魔术对你有利。 但是如果上游的rebase意外地降低了提交,那么这个魔法将会默默地阻止你把它放回去。 在这种情况下,如果你想放回那些被提交的提交,你应该改用git fetch; git rebase git fetch; git rebase

除了从远程跟踪分支更新本地分支之外,-pull还会更新您的工作区文件。

因此,git pull –rebase(或者默认configurationpull使用rebase)比git fetch更为典型。 git rebase。