我什么时候应该使用 git pull --rebase?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2472254/
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-10 08:04:54  来源:igfitidea点击:

When should I use git pull --rebase?

git

提问by Jason Baker

I know of some people who use git pull --rebaseby default and others who insist never to use it. I believe I understand the difference between merging and rebasing, but I'm trying to put this in the context of git pull. Is it just about not wanting to see lots of merge commit messages, or are there other issues?

我知道有些人git pull --rebase默认使用,有些人坚持从不使用它。我相信我了解合并和变基之间的区别,但我试图将其放在git pull. 是不想看到大量合并提交消息,还是有其他问题?

采纳答案by P Shved

You should use git pull --rebasewhen

你应该git pull --rebase在什么时候使用

  • your changes do not deserve a separate branch
  • 您的更改不值得一个单独的分支

Indeed -- why not then? It's more clear, and doesn't impose a logical groupingon your commits.

确实——那为什么不呢?它更清楚,并且不会对您的提交强加逻辑分组



Ok, I suppose it needs some clarification. In Git, as you probably know, you're encouraged to branch and merge. Your local branch, into which you pull changes, and remote branch are, actually, different branches, and git pullis about merging them. It's reasonable, since you push not very often and usually accumulate a number of changes before they constitute a completed feature.

好吧,我想它需要一些澄清。在 Git 中,您可能知道,我们鼓励您进行分支和合并。您将更改拉入的本地分支和远程分支实际上是不同的分支,并且git pull正在合并它们。这是合理的,因为您推送的频率不高,并且通常会在构成完整功能之前积累许多更改。

However, sometimes--by whatever reason--you think that it would actually be better if these two--remote and local--were onebranch. Like in SVN. It is here where git pull --rebasecomes into play. You no longer merge--you actually commit on top of the remote branch. That's what it actually is about.

然而,有时——无论出于何种原因——你认为如果这两个——远程和本地——是一个分支实际上会更好。就像在 SVN 中一样。正是在这里git pull --rebase发挥作用。你不再合并——你实际上是在远程分支之上提交的。这就是它的实际情况。

Whether it's dangerous or not is the question of whether you are treating local and remote branch as one inseparable thing. Sometimes it's reasonable (when your changes are small, or if you're at the beginning of a robust development, when important changes are brought in by small commits). Sometimes it's not (when you'd normally create another branch, but you were too lazy to do that). But that's a different question.

它是否危险是您是否将本地和远程分支视为不可分割的事情的问题。有时这是合理的(当您的更改很小时,或者您正处于稳健开发的开始时,当重要的更改由小的提交带来时)。有时不是(当您通常会创建另一个分支时,但您懒得这样做)。但这是一个不同的问题。

回答by scode

I would like to provide a different perspective on what "git pull --rebase" actually means, because it seems to get lost sometimes.

我想就“git pull --rebase”的实际含义提供不同的观点,因为它有时似乎会迷路。

If you've ever used Subversion (or CVS), you may be used to the behavior of "svn update". If you have changes to commit and the commit fails because changes have been made upstream, you "svn update". Subversion proceeds by merging upstream changes with yours, potentially resulting in conflicts.

如果您曾经使用过 Subversion(或 CVS),您可能已经习惯了“svn update”的行为。如果您要提交更改并且提交失败,因为已在上游进行更改,则您“svn update”。Subversion 通过将上游更改与您的更改合并来继续进行,这可能会导致冲突。

What Subversion just did, was essentially "pull --rebase". The act of re-formulating your local changes to be relative to the newer version is the "rebasing" part of it. If you had done "svn diff" prior to the failed commit attempt, and compare the resulting diff with the output of "svn diff" afterwards, the difference between the two diffs is what the rebasing operation did.

Subversion 刚刚所做的,本质上是“pull --rebase”。重新制定本地更改以与较新版本相关的行为是其中的“重新定位”部分。如果您在失败的提交尝试之前完成了“svn diff”,然后将结果差异与“svn diff”的输出进行比较,则两个差异之间的差异就是变基操作所做的。

The major difference between Git and Subversion in this case is that in Subversion, "your" changes only exist as non-committed changes in your working copy, while in Git you have actual commits locally. In other words, in Git you have forked the history; your history and the upstream history has diverged, but you have a common ancestor.

在这种情况下,Git 和 Subversion 之间的主要区别在于,在 Subversion 中,“您的”更改仅作为工作副本中未提交的更改存在,而在 Git 中,您在本地有实际提交。换句话说,在 Git 中你已经分叉了历史;你的历史和上游的历史有分歧,但你有一个共同的祖先。

In my opinion, in the normal case of having your local branch simply reflecting the upstream branch and doing continuous development on it, the right thing to do is always "--rebase", because that is what you are semantically actually doing. You and others are hacking away at the intended linear history of a branch. The fact that someone else happened to push slightly prior to your attempted push is irrelevant, and it seems counter-productive for each such accident of timing to result in merges in the history.

在我看来,在让您的本地分支简单地反映上游分支并对其进行持续开发的正常情况下,正确的做法始终是“--rebase”,因为这就是您在语义上实际执行的操作。你和其他人正在破解一个分支的预期线性历史。其他人碰巧在您尝试推送之前稍微推送的事实是无关紧要的,并且每次此类时间事故导致历史合并似乎都会适得其反。

If you actually feel the need for something to be a branch for whatever reason, that is a different concern in my opinion. But unless you have a specific and active desire to represent your changes in the form of a merge, the default behavior should, in my opinion, be "git pull --rebase".

如果你真的觉得出于某种原因需要将某个东西作为一个分支,那么在我看来这是一个不同的问题。但是,除非您有特定且积极的愿望以合并的形式表示您的更改,否则在我看来,默认行为应该是“git pull --rebase”。

Please consider other people that need to observe and understand the history of your project. Do you want the history littered with hundreds of merges all over the place, or do you want only the select few merges that represent real merges of intentional divergent development efforts?

请考虑其他需要观察和了解您项目历史的人。您希望历史上到处都是数百次合并,还是只想要少数几个代表有意的不同开发工作的真正合并的合并?

回答by Cody Poll

Perhaps the best way to explain it is with an example:

也许解释它的最好方法是举个例子:

  1. Alice creates topic branch A, and works on it
  2. Bob creates unrelated topic branch B, and works on it
  3. Alice does git checkout master && git pull. Master is already up to date.
  4. Bob does git checkout master && git pull. Master is already up to date.
  5. Alice does git merge topic-branch-A
  6. Bob does git merge topic-branch-B
  7. Bob does git push origin masterbefore Alice
  8. Alice does git push origin master, which is rejected because it's not a fast-forward merge.
  9. Alice looks at origin/master's log, and sees that the commit is unrelated to hers.
  10. Alice does git pull --rebase origin master
  11. Alice's merge commit is unwound, Bob's commit is pulled, and Alice's commit is applied after Bob's commit.
  12. Alice does git push origin master, and everyone is happy they don't have to read a useless merge commit when they look at the logs in the future.
  1. Alice 创建主题分支 A,并对其进行处理
  2. Bob 创建不相关的主题分支 B,并对其进行处理
  3. 爱丽丝git checkout master && git pull。大师已经是最新的了。
  4. 鲍勃确实如此git checkout master && git pull。大师已经是最新的了。
  5. 爱丽丝 git merge topic-branch-A
  6. 鲍勃做 git merge topic-branch-B
  7. 鲍勃git push origin master在爱丽丝之前做
  8. Alice 做了git push origin master,但被拒绝了,因为它不是快进合并。
  9. Alice 查看 origin/master 的日志,发现提交与她的无关。
  10. 爱丽丝 git pull --rebase origin master
  11. Alice 的合并提交被取消,Bob 的提交被拉取,Alice 的提交在 Bob 的提交之后被应用。
  12. Alice 做到了git push origin master,并且每个人都很高兴他们将来在查看日志时不必阅读无用的合并提交。

Note that the specific branch being merged into is irrelevant to the example. Master in this example could just as easily be a release branch or dev branch. The key point is that Alice & Bob are simultaneously merging their local branches to a shared remote branch.

请注意,合并到的特定分支与示例无关。本例中的 Master 可以很容易地成为发布分支或开发分支。关键是 Alice 和 Bob 同时将他们的本地分支合并到一个共享的远程分支。

回答by krosenvold

I think you should use git pull --rebasewhen collaborating with others on the same branch. You are in your work → commit → work → commit cycle, and when you decide to push your work your push is rejected, because there's been parallel work on the same branch. At this point I alwaysdo a pull --rebase. I do not use squash (to flatten commits), but I rebase to avoid the extra merge commits.

我认为您应该git pull --rebase在与同一分支上的其他人协作时使用。你在你的工作→提交→工作→提交循环中,当你决定推送你的工作时,你的推送被拒绝了,因为在同一个分支上有并行工作。在这一点上,我总是做一个pull --rebase. 我不使用壁球(来扁平化提交),但我重新调整以避免额外的合并提交。

As your Git knowledge increases you find yourself looking a lot more at history than with any other version control systems I've used. If you have a ton of small merge commits, it's easy to lose focus of the bigger picture that's happening in your history.

随着您的 Git 知识的增加,您会发现与我使用过的任何其他版本控制系统相比,您更关注历史。如果您有大量小的合并提交,很容易失去对历史中正在发生的更大图景的关注。

This is actually the only time I do rebasing(*), and the rest of my workflow is merge based. But as long as your most frequent committers do this, history looks a whole lot better in the end.

这实际上是我唯一一次执行 rebase(*),我的工作流程的其余部分是基于合并的。但只要你最频繁的提交者这样做,历史最终看起来会好很多。

(*) While teaching a Git course, I had a student arrest me on this, since I also advocated rebasing feature branches in certain circumstances. And he had read this answer ;) Such rebasing is also possible, but it always has to be according to a pre-arranged/agreed system, and as such should not "always" be applied. And at that time I usually don't do pull --rebaseeither, which is what the question is about ;)

(*) 在教授 Git 课程时,我有一个学生因此逮捕了我,因为我也主张在某些情况下重新设定功能分支。他已经阅读了这个答案 ;) 这种重新定位也是可能的,但它必须始终根据预先安排/商定的系统进行,因此不应“始终”应用。那时我通常都不做pull --rebase,这就是问题所在;)

回答by Dustin

I don't think there's ever a reason notto use pull --rebase-- I added code to Git specifically to allow my git pullcommand to always rebase against upstream commits.

我认为没有理由使用pull --rebase——我专门向 Git 添加了代码,以允许我的git pull命令始终针对上游提交进行变基。

When looking through history, it is just never interesting to know when the guy/gal working on the feature stopped to synchronise up. It might be useful for the guy/gal while he/she is doing it, but that's what reflogis for. It's just adding noise for everyone else.

在查看历史记录时,知道从事该功能的人/女孩何时停止同步是永远不会有趣的。当他/她这样做时,这可能对他/她有用,但这就是reflog目的。这只是给其他人增加噪音。

回答by leohxj

Just remember:

只记得:

  • pull = fetch + merge
  • pull --rebase = fetch + rebase
  • 拉 = 获取 + 合并
  • pull --rebase = fetch + rebase

So, choose the way what you want to handle your branch.

因此,选择您想要处理分支的方式。

You'd better know the difference between merge and rebase :)

你最好知道合并和变基之间的区别:)

回答by hasen

I think it boils down to a personal preference.

我认为这归结为个人喜好。

Do you want to hide your silly mistakes before pushing your changes? If so, git pull --rebaseis perfect. It allows you to later squash your commits to a few (or one) commits. If you have merges in your (unpushed) history, it is not so easy to do a git rebaselater one.

您想在推动更改之前隐藏愚蠢的错误吗?如果是这样,git pull --rebase就完美了。它允许您稍后将提交压缩为几个(或一个)提交。如果您在(未推送的)历史中进行了合并,那么稍后再进行合并就不是那么容易了git rebase

I personally don't mind publishing all my silly mistakes, so I tend to merge instead of rebase.

我个人不介意发布我所有的愚蠢错误,所以我倾向于合并而不是变基。

回答by Habax

git pull --rebasemay hide a history rewriting from a collaborator git push --force. I recommend to use git pull --rebaseonlyif you know you forgot to push your commits before someone else does the same.

git pull --rebase可能对合作者隐藏历史重写git push --force。我建议git pull --rebase当您知道在其他人执行相同操作之前忘记推送您的提交时才使用。

If you did not commit anything, but your working space is not clean, just git stashbefore to git pull. This way you won't silently rewrite your history (which could silently drop some of your work).

如果你没有提交任何东西,但你的工作空间不干净,就git stash在 to 之前git pull。这样你就不会默默地重写你的历史(这可能会默默地放弃你的一些工作)。