正如你在问题中暗示的那样,最令人困惑的部分是理解本地存储库与远程存储库之间的影响,以及所有其他人与远程存储库一起工作时的部分影响。首先,就像其他答案所指出的那样,“git pull”与“git fetch”+“git merge”是完全相同的。这两个命令从您本地存储库从远程拉取/获取+合并的角度来看。这发生在您在远程上本地检出的相同分支到本地的该分支。我将首先讨论这些,然后是压缩和重置基础。
Git Pull / Git Fetch + Git Merge
假设您已经在本地检出了“master”,您将从远程获取“master”(除非您对这些命令使用了更高级的语法或标志)。让我们将远程分支称为“origin/master”。
从“origin/master”获取意味着您要获取“origin/master”的新提交,并更新您的本地跟踪引用以匹配远程上实际存在的“master”。如果“master”在本地和远程之间分歧,则将有一个从您的主分支分支出的提交,直到它们达到“origin/master”的当前位置。您尚未推送的最近提交将位于可能不同的本地“master”分支上。
然后,在合并发生时,您基本上要求将“origin/master”合并到本地的“master”分支中。如果您执行普通的合并命令,则会在本地的“master”分支上生成一个新的提交,该提交将从“origin/master”中获取所有最近的更改,并将其合并到本地的“master”分支中。如果存在冲突,则需要先解决它们,然后再提交。但是,如果您尚未在本地提交任何内容,则合并可以快进到新的“origin/master”位置,而无需做其他任何事情(您的“master”只会跳转到匹配“origin/master”的新位置)。
此时,如果在其他人推送任何内容到远程之前推送,则您的新合并提交将与您的单独提交一起推送(它们看起来像一个未命名的分支),以及原始远程提交和一个新的合并提交。
那么压缩呢?
虽然您确实询问了这个问题,但是如果您使用--squash进行合并,则会添加合并提交,但删除其他本地提交,因此历史记录中不会有额外的未命名分支。有些人喜欢这样做,因为它更加“清洁”,而其他人则喜欢看到所有历史记录(即代码分叉以及在合并提交中确切地汇总了什么)。
重置基础
当你使用rebase时,基本上是将所有本地提交记录重放到远程主分支上,这样它们就不会显示为一个单独的分支。这样可以保持本地历史记录的完整性,而不显示代码分歧,有些人认为这样更加"干净"。这与该历史记录是否重要无关。
如果在你获取之后,其他人进行了提交,那么你的推送将失败。你可以使用--force选项,但这样会完全覆盖他们的提交,因此通常被视为不好的做法,因为这会给其他人带来各种问题。在这种情况下,如果每个人都同意他的提交应该先进行,那么你需要重新进行这个过程(如果没有冲突,那么这很快、很容易),但一般来说,团队需要对这种情况制定政策,通常使用拉取请求和审核来管理推送,以便更有序地进行操作,一旦团队足够大。
还有一种思考方式,就是将你的本地主分支视为远程的一个独立分支 - 这基本上是Git的观点。实际上,在我看来,除非你准备将某些东西合并到远程分支,否则最好始终在自己的独立分支中工作。Git使得拥有一个独立分支变得如此容易、快速和无痛,这就是我所做的。