从origin/master分支和从本地master分支创建分支的区别

7
假设我们有一个远程代码仓库,并克隆到本地。我们切换到主分支(master),这样我们就拥有了本地 master 分支和远程的 remotes/origin/master 分支。然后我需要创建一个新的话题分支,一旦评审通过就将合并到远程主分支。
在从本地 master 或远程等效分支(如果有区别的话)中创建分支的优缺点是什么?这些论点是否适用于长期运行的分支?
编辑:我一直在尝试跟踪 origin/master,以便在本地分支上创建 pull request。但我注意到一个很大的问题:在 TFS 上它不允许你创建 pull request。如果你需要它,你必须将你的分支推送到 origin,这将使其与 master 分离,并跟踪新的远程分支,然后才能创建 pull request;我所说的有什么错误吗?如果没有,那么这是不从 origin/master 分支开始创建分支的一个很大的原因。

下面大多数答案忽略的一个区别是,如果您还为新分支设置跟踪信息,则git pullgit push的行为也会有所不同。请注意,当从远程引用进行分支操作时,通常会自动设置跟踪,但从本地引用进行分支操作时不会自动设置。 - André Sassi
@AndréSassi 取决于您如何从远程分支分支。 - poke
我认为大多数答案都太轻描淡写地假设本地主分支是最新的。在本地master上随意提交代码并忘记它们是很容易的。如果您手动创建分支,这可能不是什么大问题,但如果您要更多地自动化(例如,与您的工单系统集成的脚本)并将此自动化提供给许多用户,则几乎肯定要使用origin/master。既然没有必要,为什么要假设master是最新的而不是不同步的呢? - Chris
@AndréSassi,跟踪时拉取/推送的行为有什么不同? - Stefano d'Antonio
@Uno 如果没有其他参数,git pushgit pull(根据您的配置)将推送到和拉取本地分支设置为跟踪的远程分支。对于主题分支,要么您从不发布它(因此无需跟踪远程),要么将其作为主题分支本身发布(在这种情况下,它将跟踪自己的远程,例如 origin/my-topic)。 - poke
5个回答

2
假设master与其远程跟踪分支origin/master保持最新状态,则实际上没有任何区别。
分支只是指向历史提交的指针,因此在一个分支上创建分支时,您只是创建了指向相同目标的另一个指针。该指针与“原始指针/分支”没有关系;它只指向一个提交。因此,当您在新分支上继续工作时,新的提交将仅使用提交的父关系引用基础。分支本身与历史记录完全无关。
Git有一种在分支中添加某种元数据的方法。但是,标准的分支机制,例如使用git branchgit checkout -b,不会使Git附加任何其他元数据到分支。
唯一相关的元数据将是远程跟踪分支。但通常,您不会想要有多个分支跟踪相同的上游分支。
因此,在您创建功能分支或其他内容时,只需从masterorigin/master创建分支即可。这并不重要。

如果主分支和origin/master不同步怎么办?是不是只需要从origin/master拉取更改到主分支,然后合并我的分支就可以了? - Stefano d'Antonio
如果它们不同步,那么从master分支出去将把新分支放在与master相同的提交上,而从origin/master分支出去将把新分支放在该提交上。它不会影响masterorigin/master。在合并时,它取决于您合并事物的顺序。例如,如果您从origin/master分支出去,然后做了一些工作,最后将该新分支合并到master中,那么您也间接地将来自origin/master(从那个时间起)的更改合并到master中。 - poke
当您间接地从 origin/master 拉取更改时,它们可能会与我的主题分支更改发生冲突;在这种情况下,这两种方法是否有任何区别? - Stefano d'Antonio
我不确定你所说的“间接拉取”是什么意思。当你在自己的主题分支上,并从origin/master拉取更改时,基础分支是什么并没有区别。 - poke
我在引用你的评论:“那么你间接地也会拉取来自origin/master的更改”。 - Stefano d'Antonio
哦,对了。我的意思是,那些存在于 origin/master 但不存在于 master 上的更改也包含在您的主题分支中(当您从 origin/master 分支时),因此,当您稍后合并该主题分支时,您也会包括这些更改。如果 master 没有分叉,那么您不应该遇到任何冲突;如果它分叉了,您将遇到与仅将 origin/master 拉到 master 上时相同的冲突。 - poke

2
运行git fetch命令将始终使origin/master保持最新状态,因此在大多数环境中,优先选择origin/master可能是正确的。当使用主题分支进行所有开发时,我发现本地的master很烦人,因为尽管它没有用处,但我还是感到有必要不时地更新它,因此我更喜欢将其删除。
偏爱将本地master作为开发基础的一个可能原因是您对其有更多的控制权。如果某人对远程master执行了错误的强制推送,当您尝试将其合并到本地master时,您很可能会注意到它,而origin/master将自动指向新历史记录。或者,您希望拥有稳定的开发基础,同时仍能够获取上游更改?

拥有本地 master 的一个原因是能够合并主题分支中的内容。 - poke
更喜欢使用 origin/master 的好解释;我不确定你支持本地分支的观点,能否请您澄清一下?(如果有人进行错误的强制推送...) - Stefano d'Antonio
@poke,你不需要为此创建一个分支;只需检出origin/master并合并即可。你将会在一个分离的HEAD上工作,但在推送之前,你只需要创建单个合并提交--无需命名。这实际上是相同的论点:本地的master需要更多的努力来确保它是最新的,当合并(而不是创建分支)时,这一点更加重要。 - Chris
@Uno,如果你总是使用主题分支进行开发,那么在拉取时本地的master应该始终快进。如果有人用不同的历史记录覆盖了远程的master,你会注意到这一点,因为你的本地master无法快进。我认为这并不是使用本地master的一个特别有力的论据——如果错误的强制推送在你的环境中是一个问题,那么你有更大的问题。 - Chris

1
只要本地主分支与远程分支保持最新,两者没有区别。两者都在相同的提交/时间点上,所以从哪里开始并不重要。
但是,如果您对主分支进行了本地更改,并且不能保证这些更改会合并到您的新分支合并到的远程分支中,则可能希望从远程引用开始。在这种情况下,两者之间存在差异,因为两个分支包含不同的提交。
总的来说,规则是您应该从最终要合并回去的分支开始一个分支。如果您1对1跟踪远程分支,本地与远程没有区别。

所以基本上我应该从那个不太可能改变的分支开始创建分支?如果我从本地主分支创建分支并对其进行更改,会遇到什么问题?只是在将新分支中的更改推送到远程时需要更多维护工作,而不包括主分支上的新提交吗? - Stefano d'Antonio
@Uno 如我在答案中所解释的那样,新分支与您基于的分支没有关系。在“分支”时,您只需选择一个基础提交(而不是分支),该提交恰好具有临时名称(分支)。 - poke

0

我认为没有绝对的优缺点。你只是从一个分支或另一个分支的历史开始。本地主分支是你电脑上的主分支。远程主分支只是你远程电脑(服务器等)上的主分支。它们都只是在它们所在的机器上共享相同名称的分支。

唯一的区别是远程分支作为跨多个用户的中心。我强调“作为”因为git中没有强制要求远程分支成为“中心”。它只是作为惯例被你的团队用作中心。

可能会有一些微妙的优势,比如你可以通过从其中一个分支创建分支来隐式设置上游分支。或者你可以直接从远程分支创建分支,而不必担心本地主分支与远程分支不完全同步。

考虑到所有这些,我甚至不确定如何基于远程分支而不是本地分支创建分支...但假设它可以完成,上述内容应该是准确的=)。


如果本地主分支不与origin/master同步,而我从本地主分支创建分支,会出现什么问题? - Stefano d'Antonio

0

没有什么特别的区别,通常情况下,如果您想创建一个名为Branch1的新分支,您将从git服务器中将最新提交的master检出到您的本地系统,然后将master代码检出到名为Branch1的新本地分支,并在提交后将Branch1推送到git服务器。这里的重点是确保您的主代码是最新的。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接