简体   繁体   English

来自标签的Git分支 - 内部

[英]Git branch from tag - internals

In git, supposing I have a branch master and a tag 0.0.1, if I do the following: 在git中,假设我有一个分支主机和一个标签0.0.1,如果我执行以下操作:

git checkout 0.0.1
git branch -b random-fix
# some changes...
git checkout master
git merge random-fix

The branch from tag, internally, creates a reference to the commit marked by the tag in the branch master or the branch is from the "tag itself", as if the tag was some kind of branch? 标签内部的分支在内部创建对分支主机中标签标记的提交的引用,或者分支来自“标签本身”,就好像标签是某种分支一样?

I'm asking this because when I checkout to a tag, I will be in a "detached head" or something like that, right? 我问这个是因为当我签到标签时,我会处于一个“独立的头”或类似的东西,对吧? Knowing that made me think about the branch-from-tag. 知道这让我想到了分支标签。

Tags Reference Commits 标签参考提交

Tags are references to commits. 标签是对提交的引用。 Specifically, lightweight tags are just refs that point to a given commit using a user-defined name. 具体来说,轻量级标签只是使用用户定义的名称指向给定提交的引用。 For example: 例如:

$ git log
commit e0e92bc337b246696aec5c214507321c7526c1e9
Author: John Doe <john.doe@example.com>
Date:   Thu Sep 26 14:38:36 2013 -0400

    Empty initial commit.

$ git tag v0.0.1

$ cat .git/refs/tags/v0.0.1 
e0e92bc337b246696aec5c214507321c7526c1e9

The actual SHA-1 is the same in both cases. 在这两种情况下,实际的SHA-1都是相同的。 Put another way, the tag is just a pointer to the commit. 换句话说,标记只是提交的指针。

Use the Tag as a Commit Identifier 使用标记作为提交标识符

You can branch from a tag the exact same way as you do from a commit identifier. 您可以使用与提交标识符完全相同的方式从标记分支。 For example, the following two commands are effectively the same thing: 例如,以下两个命令实际上是相同的:

  • git checkout -b new_branch v0.0.1
  • git checkout -b new_branch e0e92bc337b246696aec5c214507321c7526c1e9

It makes no difference to Git whether the starting point for the new branch is listed as a tag, SHA-1, or some other form of revision selection. Git对新分支的起点是否列为标签,SHA-1或其他形式的修订选择没有区别

(This should perhaps be a comment but it's way too too big and needs nice formatting :-) ... also, I appear to be in a quirky mood, if you follow some of the links...) (这应该是一个评论,但它太大了,需要很好的格式:-) ...而且,如果你按照一些链接,我似乎是一个古怪的心情...)

The key to understanding this—I think you're already there, but let's put this in the SO article to make it clear to the next reader—is this: 理解这一点的关键 - 我认为你已经存在了,但让我们把它放在SO文章中以便向下一位读者说清楚 - 这是:

All git refs wind up naming (pointing to) a single commit. 所有git引用最终命名(指向)单个提交。

This is true for tags (whether lightweight or annotated), branches, "remote branches", git "notes" references, the "stash", and so on. 对于标签(无论是轻量级还是带注释的),分支,“远程分支”,git“notes”引用,“stash”等都是如此。 They all name one commit, and that's it. 他们都命名一个提交,就是这样。 (Well, OK, not quite: technically, tags can name any object in the repo. In fact, that's how annotated tags work: there's a lightweight tag that names a repository object that is the annotated tag, and then the annotated tag names a commit object. That's also how HEAD works: it usually names another ref, which then names the commit. So, sometimes you have to peel a few layers off the onion to hit the commit. Naming a blob or tree object is possible, but normally, nothing actually does this.) (嗯,好吧,不大:从技术上讲,标签可以命名的回购任何物体其实,这就是标签如何被注解工作:有一个轻量级的标签名称资源库对象,它注释标记,然后注释标记名称提交对象。这也是HEAD工作方式:它通常命名另一个引用,然后命名提交。所以,有时你必须从洋葱上剥下几层才能命中提交。命名一个blob或tree对象是可能的,但通常,实际上没有这个。)

(The "true name" of the commit is, of course, the SHA-1 value.) (提交的“真实名称”当然是SHA-1值。)

What makes a branch reference name "special" is equally simple: 什么使分支参考名称“特殊”同样简单:

A branch reference is a name that automatically moves to the new branch tip, when new commits are added. 分支引用是在添加新提交时自动移动到新分支提示的名称。

Specifically, a ref of the form refs/heads/ branchname points to some commit (by definition, since names point to commits). 具体来说,表单refs/heads/ branchname指向某个提交(根据定义,因为名称指向提交)。 When you are "on" that branch 1 and do some git operation that adds a new commit, like git commit or git merge or git cherry-pick , git sticks the new commit into the repo, then re-points the name to the new commit. 当你在那个分支1 “上”并做一些添加提交的git操作时,比如git commitgit mergegit cherry-pick ,git将新提交粘贴到repo中,然后将名称重新指向新的承诺。 That's all it has to do! 这就是它所要做的一切!

What we think of as "the branch" is formed by starting at the tip—the commit to which the name points—and working backwards, using each commit's parent or parents. 我们所谓的“分支”是通过从提示开始形成的 - 名称指向的提交 - 并使用每个提交的父级或父级向后工作。 If the commit has one parent, it's an ordinary commit "on the branch". 如果提交有一个父级,则它是“在分支上”的普通提交。 If it has two or more, it's a "merge", and you can follow all of its parents to find what got merged. 如果它有两个或更多,它是一个“合并”,你可以跟随它的所有父母找到合并的内容。 If it has no parents at all, it's a root commit (like the initial commit in a new repo—you can actually have more than one root; git "notes" do this, for instance). 如果它根本没有父项,那么它就是一个root提交(就像新的repo中的初始提交一样 - 你实际上可以拥有多个root; git“notes”就这样做了)。

If you put seven branch labels onto one commit, you now have seven 2 names for "the branch". 如果您将七个分支标签放在一个提交上,那么现在您有七个2个名称用于“分支”。 If you clear this down to one, it's less confusing , of course, but git won't care either way. 如果你把它清除为一个,当然,它不那么令人困惑 ,但是git也不会在意。 (Git only cares if you take it down to zero names. Now the branch still exists, but it's really hard to find, and it's eligible for garbage collection .) (Git只关心你是否把它归结为零名。现在分支仍然存在,但它很难找到,并且它有资格进行垃圾 收集 。)

Since we're on the topic, let's also make a note about " remote branches". 既然我们正在谈论这个话题,那么我们也要记下“ 远程分支”。 (I have never been quite satisfied with the name "remote branch" but I don't have a better one, so let's just define it.) A "remote branch" is a local ref of the form refs/remotes/ rname / bname , where rname is the name of the remote (such as origin ) and bname is the branch name on the remote, ie, the part that comes after refs/heads/ if you log in on that remote and look at the branch over there. (我从来没有对“远程分支”这个名称感到满意,但我没有更好的,所以让我们定义它。)“远程分支”是表单refs/remotes/ rname / bname本地引用,其中rname是远程的名称(例如origin ), bname是远程的分支名称,即refs/heads/之后的部分,如果您登录该远程并查看那里的分支。 You can't get "on" a remote branch—if you git checkout origin/master , git gives you a "detached HEAD" —but these branch names are automatically updated: when you use git fetch to get new commits from the remote, you also pick up the new branch-tips. 你不能“开启”一个远程分支 - 如果你git checkout origin/master ,git会给你一个“分离的HEAD” - 但是这些分支名称自动更新:当你使用git fetch从远程获取新的提交时,你也拿起了新的分支小贴士。 In other words, instead of you moving the names to the new branch tips, you let someone else do it (on the remote) and then you pick up their latest version all at once, when you fetch from them. 换句话说,而不是移动名到新的枝梢,你让别人去做(遥控器上),然后拿起自己的最新版本,一次全部,当你从他们那里获取。


1 To be "on a branch", the HEAD ref must be an "indirect" reference, something like ref: refs/heads/master . 1要成为“在分支上”, HEAD ref必须是“间接”引用,类似于ref: refs/heads/master When HEAD is instead "detached" it contains a raw SHA-1 value. HEAD改为“分离”时,它包含原始SHA-1值。 You can still add commits; 你仍然可以添加提交; they're added to an un-labeled branch. 它们被添加到未标记的分支中。 The reference in HEAD keeps them from being garbage-collected. HEAD的引用使它们不被垃圾收集。

2 Or more, if there are tags. 2或更多,如果有标签。 Let's assume there are no tags . 我们假设没有标签

3 There is no footnote three. 3没有脚注三。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM