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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/6284887/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-19 05:33:37  来源:igfitidea点击:

What's the difference between `git fetch` then `git rebase`, and `git pull --rebase`?

gitgit-rebase

提问by Ryan Lundy

In reading the git pullpage, it gives this stern warning about git pull --rebase:

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

This is a potentially dangerous mode of operation. It rewrites history, which does not bode well when you published that history already. Do not use this option unless you have read git-rebase(1) carefully.

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

In the git rebasepage, it gives a lot of description but no warning of this sort.

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

In addition, I've seen some people say that

另外,我看到有人说

git fetch
git rebase

is the same as

是相同的

git pull --rebase

while others say they're slightlydifferent.

而其他人则说它们略有不同。

What's the truth?

真相是什么?

采纳答案by Seth Robertson

The rule with Git is that you should never attempt to change history after it has been shared, published, or pushed. You can do so, of course, if you really want to and have sufficient permissions, but it should be done with great care since it can mess other people up.

Git 的规则是,在共享、发布或推送历史记录后,永远不要尝试更改它。当然,如果您真的想要并拥有足够的权限,您可以这样做,但应该非常小心,因为它可能会弄乱其他人。

Now fortunately when you have a typical Git deployment with a single upstream repository (origin) which is the source of all that is good and true in the universe, you can use git pull --rebaseto your heart's content and it will be perfectly safe and in my opinion give you a much more sane (meaning linear) history. I and my team use it continuously.

现在幸运的是,当你有一个典型的 Git 部署时,它有一个单一的上游存储库(源),它是宇宙中所有美好和真实的来源,你可以尽情使用git pull --rebase它,这将是非常安全的,在我看来你是一个更加理智(意味着线性)的历史。我和我的团队一直在使用它。

However, if you start having multiple remotes and start doing git pull --rebase <arguments>so that you are no longer rebasing against the same target every time, or start pushing your branch to alternate repositories beforerunning git pull --rebasewith your primary upstream—then you can start running into troubles.

但是,如果您开始拥有多个远程服务器并开始这样做,git pull --rebase <arguments>那么您不再每次都针对同一个目标进行重新定位,或者git pull --rebase与主要上游运行之前开始将您的分支推送到备用存储库- 那么您可能会开始遇到麻烦。

Any time where you share your changes with another remote/repository and then change those changes (for values of changing equal to changing the SHA, parent, etc. even if the commit message/content did not change), you can mess up the person who had the old changes.

任何时候您与另一个远程/存储库共享您的更改,然后更改这些更改(对于更改等于更改 SHA、父级等的值,即使提交消息/内容没有更改),您可能会搞砸这个人谁有旧的变化。

As long as you don't fall outside the envelope of rebase sanity, git pull --rebasewill be very good for you.

只要你不脱离 rebase sanity 的范围,git pull --rebase就会对你非常有好处。

That, err, doesn't answer the question about the difference between git pull --rebaseand git fetch && git rebase @{u}. I'll just go ahead and say that I am unaware of any difference and if there is one, it is subtle enough that I have not noticed it in the years I have used Git. Possibly in that the system figures out the correct repository your branch should fetch if you have multiple repositories and "origin" isn't the upstream of this branch?

也就是说,呃,不回答之间的差异问题git pull --rebasegit fetch && git rebase @{u}。我会继续说我不知道​​有任何区别,如果有的话,它很微妙,我在使用 Git 的这些年里没有注意到它。可能是因为如果您有多个存储库并且“源”不是该分支的上游,系统会找出您的分支应该获取的正确存储库?

And even if you do go very awry with git-rebase, you can of course recover yourself back to your original pre-rebase environment easily with git log -gand/or git reset --hard ORIG_HEAD. Just don't do force pushes (disallowed by default in almost all Git servers), and you will be happy happy.

即使您确实在使用 git-rebase 时出错,您当然可以使用git log -g和/或轻松地将自己恢复到原始的预变基环境git reset --hard ORIG_HEAD。只是不要强制推送(默认情况下几乎所有 Git 服务器都不允许),你会很高兴的。

EDITED

已编辑

With time my understanding has expanded. git pull --rebasecalls git rebaseto do the rebase work, so in that sense there is no difference between them. However, git-pull actually calls git rebase --onto @{u} $(git merge-base HEAD @{u}@{1})

随着时间的推移,我的理解得到了扩展。git pull --rebase调用git rebase执行 rebase 工作,因此从这个意义上说,它们之间没有区别。然而, git-pull 实际上调用git rebase --onto @{u} $(git merge-base HEAD @{u}@{1})

OK, that syntax ("@{u}@{1}") is perhaps a little opaque and is a simplification to boot, but the point is that it finds out what the merge base was to upstream BEFOREit ran the fetch command. What difference does this make, you ask?

好的,该语法(“@{u}@{1}”)可能有点不透明,并且简化了引导,但关键是它运行 fetch 命令之前找出上游的合并基础。你问这有什么区别?

Well, in the normal case none. However, if you are changing where upstream is pointing to or if upstream itself was rebased, quite a lot. If upstream was rewritten and then you did a git rebase @{u}you could be very unhappy and could get double-commits or conflicts depending on how much the older commits were rewritten.

好吧,在正常情况下没有。但是,如果您正在更改上游指向的位置或者上游本身是否已重新定位,那么很多。如果上游被重写,然后你做了一个git rebase @{u}你可能会非常不高兴,并且可能会出现双重提交或冲突,这取决于旧提交的重写量。

However, with the magic behind git pull --rebaseonly the commits which are yours and yours alone will be applied on top of @{u}.

然而,凭借背后的魔力,git pull --rebase只有你自己的提交才会应用在@{u} 之上。

OK, this toois a simplification. If upstream did a rebase starting with the 100 commits ago (but there are actually 101+ commits in history) andyou did a git fetchbeforedoing a git pull --rebasethen Git will not be able to accurately determine what the proper historical merge-base was to figure out what your local commits are.

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

The upshot of which is, git fetchis considered harmful (when you have local commits and upstream is rewritten). However, the real rule-of-thumb is "never attempt to change history after it has been shared, published, or pushed" which is where I started.

其结果是,git fetch被认为是有害的(当您有本地提交并且上游被重写时)。然而,真正的经验法则是“在历史被共享、发布或推送后,永远不要试图改变它”,这就是我开始的地方。

TL;DR:

特尔;博士:

git fetchis considered harmful (so use git pull --rebase); and never attempt to change history after it has been shared, published, or pushed (because, among other things, it will cause git fetchto be harmful).

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

回答by Adam Spiers

The truth is that they AREdifferent. Here's a really helpful web page which explains it beautifully:

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

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

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

So git pull --rebasehas some significant magic over git fetch; git rebasewhich most of the time you won't notice, but in cases where the upstream maintainer has naughtily ignored all those stern warnings and decided to rewrite the history of a public branch, it can really help out by consulting your local reflog and doing the local rebase in a more intelligent way.

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

That said, this is still a rebase, so you are still rewriting history! Therefore all the standard stern warnings still apply. But if you're working on a private (i.e. unpublished) branch, then that's OK.

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

I'll say a bit more regarding the stern warnings. They are valid, but personally I find most people just a bit tooparanoid about rebase, like a git rebasecrept into their bedroom in the middle of the night when they were young and ate their sister or something. It really shouldn't be that scary:

关于严厉的警告,我会多说一点。它们是有效的,但就我个人而言,我发现大多数人对 rebase有点过于偏执,就像git rebase他们小时候在半夜爬进他们的卧室,吃掉了他们的妹妹之类的东西。它真的不应该那么可怕:

  • if it's a private branch, rebase to your heart's content
  • if it's a public branch don't rebase unless you reallyhave to, and if you do, make sure you understand the impact, and make sure anyone who might be impacted is properly informed about what you've done, so they don't get a nasty surprise and waste a load of time figuring out what happened.
  • 如果它是私人分支,请根据您的喜好重新设置
  • 如果它是一个公共分支,除非你真的必须,否则不要 rebase ,如果你这样做,确保你了解影响,并确保任何可能受到影响的人都正确地了解你所做的事情,所以他们不会得到一个令人讨厌的惊喜并浪费大量时间弄清楚发生了什么。

It's that simple. And yes, I would go as far as actively encouraging people to regularly git rebase -ion their private branches. Polishing history before pushing to somewhere public/upstream is a good thing, because no one wants to wade through a project's history which is full of commits like 'oops, fixing a mistake I made 3 commits ago'. (OTOH, don't get totally obsessed with rebasing in quest of a flawless history. We're human. We make mistakes. Deal with it.)

就这么简单。是的,我会积极鼓励人们定期git rebase -i访问他们的私人分支机构。在推送到公共/上游某个地方之前完善历史记录是一件好事,因为没有人愿意涉足一个项目的历史,它充满了诸如“哎呀,修复了我在 3 次提交前犯的错误”之类的提交。(OTOH,不要完全沉迷于重新定位以寻求完美的历史。我们是人类。我们会犯错误。处理它。)

One last observation regarding the git pull --rebasemagic. If the upstream public branch has been rebased in a sensible way (e.g. squashing / fixing up commits, or dropping commits which shouldn't have been put there) then the magic works in your favour. However if the upstream rebase accidentally droppedcommits, then the magic will silently prevent you from putting them back. In this case if you want to put back those dropped commits, you should instead use git fetch; git rebase.

关于git pull --rebase魔法的最后一个观察。如果上游公共分支以合理的方式重新定位(例如压缩/修复提交,或删除不应该放在那里的提交),那么魔法对你有利。然而,如果上游 rebase 不小心丢弃了提交,那么魔法会默默地阻止你把它们放回去。在这种情况下,如果你想放回那些丢弃的提交,你应该使用git fetch; git rebase.

回答by Rick O'Shea

In addition to updating your local branch from its remote tracking branch, the -pullupdates your workspace files.

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

So it's probably more typical to git pull --rebase(or configure pull to use rebase by default) than to git fetch; git rebase.

因此git pull --rebase(或配置 pull 以默认使用 rebase)可能比 to更典型git fetch; git rebase