`git fetch`然后`git rebase`和`git pull --rebase`有什么区别?

Rya*_*ndy 41 git git-rebase

在阅读git pull页面时,它给出了以下严厉的警告git pull --rebase:

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

git rebase页面中,它提供了大量描述,但没有这种警告.

另外,我见过有人这么说

git fetch
git rebase
Run Code Online (Sandbox Code Playgroud)

是相同的

git pull --rebase
Run Code Online (Sandbox Code Playgroud)

而其他人说他们略有不同.

真相是什么?

Ada*_*ers 38

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

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

所以git pull --rebase有一些重要的魔力git fetch; git rebase,大多数时候你都不会注意到,但是如果上游维护者顽皮地忽略了所有那些严厉的警告,并决定重写公共分支的历史,那么通过咨询你的确可以提供帮助.本地reflog并以更智能的方式进行本地rebase.

也就是说,这仍然是一个改变,所以你仍然在重写历史!因此,所有标准的严厉警告仍然适用.但是,如果你正在开发一个私人(即未发布)分支,那就没关系.

关于严厉的警告,我会多说一点.它们是有效的,但就我个人而言,我发现大多数人对于变形有点过于偏执,就像git rebase他们年轻时半夜悄悄潜入卧室并吃掉他们的妹妹一样.真的不应该那么可怕:

  • 如果它是一个私人分支,那么就要重新考虑内心
  • 如果它是一个公共分支,除非你真的需要,否则不要改变,如果你这样做,确保你理解其影响,并确保任何可能受影响的人都知道你做了什么,所以他们不得到一个令人讨厌的惊喜,并浪费了一大堆时间搞清楚发生了什么.

就这么简单.是的,我会积极鼓励人们定期git rebase -i在他们的私人分支机构.在推送到公共/上游的某个地方之前抛光历史是一件好事,因为没有人想要涉及一个项目的历史,这个历史充满了像'oops,修复我犯过的3个提交之前的错误'.(OTOH,不要完全沉迷于寻求完美历史的变革.我们是人.我们犯错误.处理它.)

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


Set*_*son 30

使用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-底垫中,你当然可以用自己恢复回原来的预变基环境容易git log -g和/或git reset --hard ORIG_HEAD.只是不要强行推送(在几乎所有的Git服务器中都默认不允许),你会很开心.

EDITED

随着时间的推移,我的理 git pull --rebase要求git rebase进行rebase工作,所以从这个意义上说它们之间没有区别.但是,git-pull实际上是调用git rebase --onto @{u} $(git merge-base HEAD @{u}@{1})

好的,那个语法("@ {u} @ {1}")可能有点不透明,并且是一个简化的引导,但重点是它运行fetch命令之前找出了合并基础到上游的内容.你问,这有什么不同?

那么,在正常情况下没有.但是,如果您正在改变上游所指向的位置,或者上游本身是否已经重新定位,那么就会非常多.如果上游被重写然后你做了一个,git rebase @{u}你可能会非常不满意,并且可能会得到双重提交或冲突,具体取决于旧的提交被重写的程度.

然而,git pull --rebase只有你自己的提交背后的魔力,你自己的提交将应用于@ {u}之上.

好的,这也是一种简化.如果上游从100个提交开始做了一个rebase(但实际上有101个提交历史)并且你做了git fetch 之前做了一个git pull --rebase然后Git将无法准确地确定什么是正确的历史合并基础来弄清楚什么你的本地提交是.

其结果是,git fetch被认为是有害的(当你有本地提交和上游被重写).然而,真正的经验法则是"在共享,发布或推送之后永远不会尝试改变历史",这是我开始的地方.

TL; DR:

git fetch被认为是有害的(所以使用git pull --rebase); 并且在共享,发布或推送之后永远不会尝试更改历史记录(因为,除其他外,它将导致git fetch有害).

  • TLDR 是错误的:`git fetch` 不可能有害!它除了从远程获取新对象之外什么也不做。它不会以任何方式改变本地结账或本地分支机构的状态。 (2认同)