【问题标题】:Checkout git tags present on multiple branches签出多个分支上的 git 标签
【发布时间】:2018-11-27 11:15:52
【问题描述】:

我阅读了很多 SO 帖子,但没有一篇让我了解 git 标签的真正工作原理,尤其是关于它们与分支的链接。我认为这是由于对git原理的误解。也许有人可以帮助我。

假设我有以下两个分支 master 和 develop 与 K 合并提交:

-A-B-C-D-E-F-G-K-L-M (master)
       \-H-I-J-/     (develop)

如果我标记J 提交,则此标记将位于两个分支上(因为合并)。 那么当我checkout这个标签时,我会有什么版本呢?包含E,F,G 提交的master 分支或来自develop 分支的提交。不确定我是否清楚我想了解的内容。我知道标签不引用分支,而只是提交。但是签出标签也可以恢复历史提交不是吗?

【问题讨论】:

  • “尤其是关于他们与分支机构的链接” -- 没有这样的链接。
  • “假设我有以下两个分支master 和develop”——一个分支是指向提交的指针。您没有在图中显示两个分支指向的提交。
  • 确实,我的图不是很清楚,但是第一行是我的master 分支,第二行是我的develop 分支
  • 为了更清楚,我的问题是:如果我签出我的标签,我会处于 ABCDHIJ 提交状态还是 ABCDEFGHIJ 状态?
  • 我猜你的意思是master 指向M 和develop 指向J。您应该将这些信息放在图纸中。

标签: git git-branch git-checkout git-tag


【解决方案1】:

您可以签出标签,但这会使您的存储库处于分离的 HEAD 状态。本质上不在任何分支上。

见Git Tagging。

【讨论】:

  • 所以这个状态不会包含在两个分支中所做的任何修改?这就是你的意思?
  • 你的本地存储库在这种状态下将有任何提交,直到并包括标记的提交,所以我猜是的。
  • 好的,例如,当我从 GitHub 下载标签存档时,我会恢复 master 分支或 develop 分支的版本(最初提交的位置)吗?
  • 你标记了一个特定的提交,所以这取决于这个提交是如何合并的。我使用 Git Extensions 作为我的 Git 工具,它以非常清晰的方式可视化当前状态下的所有提交。你可能想看看那个。
【解决方案2】:

我假设树枝的位置是这样的(反正没关系):

                     v------- master
-A-B-C--D-E-F--G-K-L-M
      \-H-I-J-/
            ^------ develop

如果我标记J 提交,这个标记将在两个分支上(因为合并)。

标签是指向提交的只读指针。一个分支也指向一个提交,但它被许多 Git 命令移动到另一个提交(git commit、git merge、git rebase、git pull、git reset 是最常见的)。

鉴于两个分支的当前位置,J 提交确实可以从两个分支到达。 git commit、git merge 和 git pull 不会改变这个现状。但是git reset 或git rebase 可以在不是J 后代的提交上移动分支,在这种情况下,J 将无法从移动的分支访问。

那么当我签出这个标签时,我会得到什么版本?包含master 分支的E、F、G 提交的一个或来自develop 分支的一个。

git checkout 将您的工作副本更改为与签出的提交相同。

如果您将分支传递给git checkout,它也会使该分支成为当前分支(又名HEAD)。如果您将非分支的引用传递给git checkout(它可以是标签、提交哈希或解析为单个提交的其他revision specification),那么您将存储库置于名为"detached HEAD" 的状态.这意味着没有当前分支。
不建议在分离的HEAD 状态下工作(除非您知道自己在做什么),因为以这种方式创建的提交不会被任何分支指向,并且一旦您签出另一个分支就会丢失(或标记或提交)。

假设你运行:

git tag tagJ J

要在提交J 时创建名为tagJ 的标签,以下两个命令执行相同的操作:

git checkout J
git checkout tagJ

他们更改工作树和索引以匹配提交J 中记录的项目状态。他们将 repo 设置为 detached HEAD 状态。

命令:

git checkout develop

以与上述两个命令相同的方式更改工作树和索引。但是,它不会将 repo 设置为 detached HEAD 状态,而是将 develop 设置为 HEAD(当前分支)。

但是签出标签也可以恢复历史提交不是吗?

历史由分支和标签决定。可以从任何分支或标签访问的任何提交都是历史的一部分。如果你删除了master 分支fe,你的repo 的历史将只包含可以从develop 分支访问的提交(即A、B、C、H、I和J)。如果您删除develop 分支(并保留master 分支),您不会丢失任何内容,因为绘图中可见的所有提交都可以从提交M(由master 分支指向)访问。

【讨论】:

  • 首先,感谢您提供如此详细的回答。我问自己这样一个问题是因为我想通过 git 标签来处理我的发布。我希望能够从标签中签出源代码以构建发布版本。当我们使用 GitHub 并创建标签时,它允许我们下载存档。但我不知道恢复的是哪个版本,是来自master 的版本还是来自develop 的版本。如果我很好理解你的回答,因为 J 提交可以从两个分支访问,GitHub 存档也将包含 master 提交,不是吗?
  • 没有。如果您签出master 或develop,提交J 引入的更改将包含在签出的工作树中(当然,如果它们没有被以后的提交撤消),因为J 可以从这些分支访问。但是,如果您签出J,那么您将只能获得从J 开始可访问的提交引入的更改。如果提交 X 是提交 Y 的祖先,则提交 X 可以从提交 Y 访问。如果您签出提交J,那么您将仅获得提交A、B、C、H、I 和J 引入的更改...
  • ...你不会得到提交D、F、G、K、L和M引入的更改.
  • 可达性只在一个方向起作用:从子提交到父提交。
  • 它将是J 提交的状态(以及一个分离的HEAD)。请记住,develop 分支可以移动或删除。您可以将develop 分支点设置为提交G,这样它就不再与提交J 相关。分支只是引用提交及其历史的一种方便方式。它们不是永久性的。提交和标签是永久性的(在某种程度上)。
猜你喜欢
  • 2013-03-26
  • 2019-04-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-07-23
  • 2021-12-08
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多