使用Git时,如何判断新分支是基于哪个分支创建的? [英] When using Git, how to tell which branch a new branch is created based on?

查看:290
本文介绍了使用Git时,如何判断新分支是基于哪个分支创建的?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如果我做了一个

git checkout -b bar foo

git checkout foo
git branch bar

都应该在分支foo的基础上创建分支bar.但是让我们说第二天,如果我想验证bar确实是基于foo创建的,那么在git中没有简单的方法可以做到这一点,或者存在吗?

both should have created a branch bar base on the branch foo. But let's say the next day, if I want to verify that bar really was created based on foo, there is no easy way to do that in git, or is there?

使用应用程序SourceTree,似乎有可能并且很容易看出,如果barfoo显示在同一行上,则表示在该阶段它们是相同的,并且如果我在bar,它将在树图中显示bar是从foo扩展的,因此我可以很容易地看出bar是基于foo的.我在SO中发现的其他一些问题似乎暗示着没有简单的方法可以说出来,但是我不明白为什么.至少在有可能告诉的情况下,不应该有一个告诉它的命令,例如git branch --show-base-on之类的东西,并且在不可能指示时,显示不能告诉,因为[由于某种原因]" ?

Using the app SourceTree, it seems it is possible and easy to tell, that if bar and foo are displayed on the same row, that means they are the same at that stage, and if I commit anything in bar, it will show that bar is "extended" from foo in the tree graph, so I can easily tell bar was based on foo. Some other questions I found in SO seem to suggest there is no easy way to tell, but I don't understand why. At least when it is possible to tell, shouldn't there be a command that tells it, such as something like git branch --show-base-on or something like that, and when not possible to tell, then display "cannot tell because [some reason]"?

推荐答案

git checkout -b bar foo的最后一个参数实际上只是一个提交ID.您使用了分支名称foo,但是git将其解析为提交ID.结果是git用相同的提交ID创建了新的分支标签bar.

The last argument to git checkout -b bar foo is really just a commit-ID. You used the branch name foo, but git resolves this to a commit-ID. The effect is that git creates the new branch label bar with that same commit-ID.

假设您有以下提交图:

A <- B <- C <- D
            \
              E

(ASCII没有合适的上下箭头,因此可以想象\的箭头指向C,即,提交E的父提交是C).每个字母代表一个与提交对应的唯一SHA-1 ID.提交D具有其(单个)父作为提交C,提交E也是如此,因此分支在提交C处分叉.

(ASCII does not have a proper up-and-left arrow so imagine the \ as having an arrow-head pointing to C, i.e., the parent commit of commit E is C). Each letter represents one unique SHA-1 ID corresponding to a commit. Commit D has its (single) parent as commit C, and so does commit E, so the branches fork at commit C.

现在,让我们也粘贴一些分支标签.名为bra的分支包含提交A的提交ID,因此它指向A.名为brb的分支包含提交B的提交ID,因此它指向B.分支brc指向C,依此类推. (我不能真正用ASCII正确地绘制所有这些图像,因此我们必须简单地想象它们.)

Now let's paste on some branch labels as well. The branch named bra contains the commit ID of commit A, so it points to A. The branch named brb contains the commit ID of commit B, so it points to B. Branch brc points to C, and so on. (I can't really draw all of these properly in ASCII so we must simply imagine them.)

让我们再创建一个分支,例如master,它也指向提交D.

Let's make one more branch, say, master, that also points at commit D.

对于超混凝土而言,假设D的SHA-1是5f95c9f850b19b368c43ae399cc831b17a26a5ac.

For super-concreteness, let's say the SHA-1 for D is 5f95c9f850b19b368c43ae399cc831b17a26a5ac.

现在,如果我这样做:

git checkout -b new 5f95c9f850b19b368c43ae399cc831b17a26a5ac

您说分支new是基于哪个分支的?新的分支标签new指向提交D,就像现有的分支标签brdmaster一样.那么new是否起源于brdmaster或...?

which branch would you say branch new is based on? The new branch label new points to commit D, just like the existing branch labels brd and master. So does new originate from brd, or master, or ...?

您可能对此有一个答案,但是git没有. git中的分支标签是短暂的:它们可以随时被清除和/或重新创建或重命名. (如果删除标签master,以便仅brd指向D,则可以说分支new基于分支brd.但是如果我随后将brd重命名为bird?)

You may have an answer to this, but git doesn't. Branch labels in git are ephemeral: they can be swept away and/or re-created or renamed at any time. (If I delete the label master, so that only brd points to D, you could then say that branch new is based on branch brd. But what if I then rename brd to bird?)

git中唯一真正永久的是SHA-1值,它完全取决于基础对象的内容.创建完全相同的对象内容,您将获得完全相同的SHA-1哈希.在任何对象中的任何地方更改一点,您将获得一个新的不同的SHA-1.

The only things really permanent in git are the SHA-1 values, which depend entirely on the contents of the underlying object. Create the exact same object contents and you get the exact same SHA-1 hash. Alter a single bit anywhere in any object, and you get a new, different SHA-1.

由于提交记录了其父提交(在合并的情况下为多个父提交),所以通过从某个引用开始并向后工作至无父提交(根提交)而构造的图是永久性的(前提是起点仍保留在资源库中(即,永远不会被垃圾收集),但标签则不会. (只有在没有外部引用(分支,标签等)指向它们并且没有其他已经保留的存储库对象 1 指向它们的情况下,才对垃圾进行垃圾回收.像E这样的图形提示的单个引用足以保留整个提交链.但是,如果删除该引用,该链将变得脆弱.)

Since commits record their parent commit(s) (multiple parents in the case of a merge), the graph constructed by starting at some reference and working backwards to a parent-less commit (a root commit) are permanent (provided that the starting-point remains in the repository, i.e., is never garbage-collected), but the labels are not. (Commits are garbage collected only when no no external reference—branch, tag, etc.—points to them and no other already-retained repository object1 points to them, so a single reference to a graph-tip like E suffices to retain the entire chain of commits. But if you delete that reference, the chain becomes vulnerable.)

1 这些其他存储库对象"必然是其他提交或带注释的标记对象,因为它们是仅有的两个应包含提交的SHA-1的对象.带注释的标签对象本身应该由相应的轻量级标签或其他可能带注释的标签指向(引用).

1These "other repository objects" are necessarily either other commits, or annotated tag objects, as those are the only two that are supposed to contain the SHA-1 of a commit. Annotated tag objects themselves should be pointed-to—referenced—by a corresponding lightweight tag, or possibly another annotated tag.

顺便说一句,git branch可以帮助您解决其他问题.假设您有一个提交图,看起来像这样:

Incidentally, git branch can help you out if you want to ask a different question instead. Let's say you have a commit graph that looks more like this:

...-o-o-o-o-o-A   <-- master
     \     /
      o-o-B       <-- feature1
           \
            C     <-- feature2

其中每个o节点代表一个无趣的"(且未标记)的提交.此处标记的分支提示提交(ABC)是masterfeature1feature2的分支提示. (很可能feature2是通过feature1的分支创建的,而feature1是通过master的分支创建的,但这通常也不是特别有趣.)

where each o node represents an "uninteresting" (and un-labeled) commit. The labeled branch-tip commits here (A, B, and C) are the branch-tips of master, feature1, and feature2. (It's likely that feature2 was created by branching off of feature1, and feature1 was created by branching off master, but usually this is not particularly interesting either.)

如果您现在要在分支master上工作,您经常想知道的是:合并了哪些分支,而没有合并哪些分支?" git branch命令可以回答此问题:

What you often want to know, if you are to work on branch master now, is: "what branches are merged in, and what branches are not merged?" The git branch command can answer this:

git branch --merged master

和:

git branch --no-merged master

这两个命令都要求git branchmaster标识的提交(即,提交A)开始,并沿着提交图向后工作".

Both commands ask git branch to start at the commit identified by master (i.e., commit A) and "work backwards" along the commit graph.

对于--merged,它应该打印分支的名称,当从master向后进行工作时,将到达由这些分支标识的提交.因此,我们从A开始,然后回到最右边的o.这是一个合并提交(有两个父级),因此我们沿两个父级退后一步,找到下一个o提交,然后提交B.提交B由分支名称feature1指向.它是从master到达的 ,因此git branch打印feature1.这是合并到"分支master的分支.

With --merged, it should print the names of branches that, when working backwards from master, the commit identified by those branches is reached. So we start at A and step back to the right-most o. This is a merge commit (with two parents), so we then step back along both parents, finding the next o commit and commit B. Commit B is pointed-to by branch name feature1. It is reached from master, so git branch prints feature1. This is a branch that "is merged into" branch master.

对于--no-mergedgit branch命令应打印那些未达到 提交的分支.和以前一样,我们从A开始并向后工作,找到最右边的o是合并.我们沿着父母双方向后工作,找到另一个oB;继续往回走,我们发现了另外两个o,另外两个o,然后重新加入最左侧的o,并通过...部分进行了重新操作.我们什么时候都没有到达提交C,因此git branch打印feature2:这是一个 not 合并到"分支master的分支.

With --no-merged, the git branch command should print those branches whose commits are not reached. As before, we start at A and work backwards, finding the right-most o that is a merge. We work backwards along both parents, finding another o and B; continuing back we found two more os, another two os, and then rejoin the left-most o and work back through the ... section. At no point do we reach commit C—so git branch prints feature2: this is a branch that is not "merged into" branch master.

git branch的袖子还有另一个窍门(如果它有头袖的话,:-)).我们可以要求git branch --contains并为其指定特定的提交ID,或者提供任何可以解析为提交ID的内容.假设我们为它提供了提交B的ID.

There's one more trick up git branch's sleeve (if it has any sleeves in the first place :-) ). We can ask for git branch --contains and give it a particular commit-ID, or anything that resolves to a commit-ID. Let's say we give it the ID of commit B.

这次,使用--containsgit branch命令从每个分支尖端开始,然后开始向后工作.如果它可以达到我们给它的提交ID,它将打印分支名称.和以前一样,当我们从提交A(master)开始时,我们到达了提交B.当我们从提交B(feature1)开始时,我们当然会立即到达提交B.当我们从提交C(feature2)开始时,我们到达了提交B.因此git branch --contains feature1打印所有三个分支名称.

This time, with --contains, the git branch command starts at every branch-tip and begins working backwards. If it can reach the commit ID we gave it, it prints the branch-name. As before, when we start from commit A (master), we reach commit B. When we start from commit B (feature1), we of course reach commit B immediately; and when we start from commit C (feature2), we reach commit B. So git branch --contains feature1 prints all three branch-names.

(如果我们要问git branch哪个分支包含最右边的o提交,则只有master会包含它.对于大多数顶行o提交,这都是正确的最左边的一个;分支feature1feature2也包含该提交,以及...部分中的所有较早提交.)

(If we were to ask git branch which branches contain the right-most o commit, only master would contain it. The same would be true of most of the top-line o commits, except for the left-most one; branches feature1 and feature2 also contain that commit, and any earlier ones in the ... section.)

这篇关于使用Git时,如何判断新分支是基于哪个分支创建的?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆