黄线是主分支。 红线是开发分支。
我在标签6.2.1上的主人。 我需要自动获取以蓝色圈出的提交的sha1,检查这个sha1并从这个sha1创建我的分支。此提交不是开发的最后一次提交。
要做的事情可能包括:
git log --oneline | head -1 | cut -d ' ' -f1
目前我必须手动继续使用Gitlab,在签出之前获取相关的sha1,然后创建我的分支。
答案 0 :(得分:1)
有一种方法,但存在潜在的问题。
标签名称标识提交。
更具体而又准确地说,像[{1}}这样的标记名称是完全限定的引用名称v2.1
的简短版本,任何Git引用都标识了一些Git对象。所有分支名称(例如refs/tags/v2.1
都是master
的缩写)被限制为仅识别 提交对象。标记名称通常标识提交对象-Git,将其称为轻量级标记 - 或带注释的标记对象,然后继续识别提交。在任何一种情况下,special gitrevisions syntax refs/heads/master
都会引用特定提交,如果您需要(通常您不会发现,例如,name^{commit}
需要提交,自动添加git checkout
。
问题是,您不希望标记识别的提交。您需要附近的提交。你说"两次提交之后"这是一个问题:在另一次提交之后没有提交这样的事情。在另一次提交之前只有提交。
如果在提交之前有提交,那么在提交之后如何没有提交?例如,让我们连续写下四个提交:
^{commit}
在Git中,提交A <- B <- C <- D
存储其父提交的ID,即提交D
。因此,C
给出D
很容易回到C
。同样,C
存储B
的ID和B
商店A
。 (如果A
是第一次提交,那么没有父级:您无法后退,A
是 root commit 。 root commit是没有父级的。)
这里的问题是,在提交之前或提交之后,可能会有多个提交。而不仅仅是上述内容,请考虑此图片段:
A--B--C--D---H <-- master
\ /
E--F--G <-- feature
提交H
,即分支master
的提示,是 merge 提交。它有两个父母:D
和G
。当我们检查提交H
时,我们会看到类似这样的内容(使用不同的数字):
$ git show master
commit 3e5c63943d35be1804d302c0393affc4916c3dc3
Merge: c13c783 20690b2
这意味着它有两个父母,c13c783...
和20690b2...
。 在提交H
之前哪一个 提交?
因此,异议的答案是在提交之前没有 提交,有可能 - 很多(通常为1,有时为2,稀有)但在另一次提交之前偶尔会提交零或三次或更多次提交。同样,在另一次提交之后,可能没有或两次或更多次提交。
要查找您想要的提交,您需要更多信息。
一般来说,向后移动很容易。提交的第一个(通常是唯一的)父级通常是有趣的,因为它是之前的分支的提交/ em>该提交已将添加到该分支。也就是说,虽然提交H
同时将D
和 G
作为父项,但master
过去曾指向D
现在指向H
,它是我们想要的H
第一个父级。
Gitrevisions有一个快速简单的语法来跟踪前父母:你只需添加一个代字号~
字符和一个有多少第一父母退一步的计数。所以,要从v2.1
继续执行 back 两个步骤,仅关注第一个父母,只需写下v2.1~2
:
git checkout -b newbranch v2.1~2
你已经完成了。
前往前进更难。 Git只存储向后链接,因此您需要提供以后提交的名称或标识,Git可以从此向后工作以达到您已知(标记)的提交。例如,如果我们有一个指向提交C
的标记,并且我们想要向前移动两步(到D
再到H
),我们会给Git 两个< / em>信息:
v2.1
master
让它枚举这两点之间的所有提交,然后选择一两步&#34;接近master
&#34;而不是v2.1
的最后一个。现在让我们说master
现在还有更多提交,所以图纸看起来像这样:
tag:v2.1
|
v
A--B--C--D---H--I <-- master
\ /
E--F--G <-- feature
要以这种方式查找H
,我们会使用git rev-list
和yet more gitrevisions syntax。 (到目前为止,显然学习gitrevisions语法对于使用Git 至关重要。)
git rev-list v2.1..master
这里的双点语法意味着&#34; 不要包括v2.1
本身&#34;,所以这将列出从master开始提交并返回到在v2.1
之后提交:
0fbc341... # id of I
a9315c3... # id of H
9911231... # id of D
我们获取这两个ID中的最后两个,丢弃这些ID中的最后一个一个,然后获取a9315c3
,即H
的ID。
如果图表看起来更像这样怎么办?
tag:v2.1
|
v
A--B--C--D---------H--I <-- master
\ /
E--F--G <-- feature
我们之前注意到,使用~
表示法使用 first 父级。我们可以使用git rev-list --first-parent v2.1..master
来完成此操作。这将使Git无法列出G-F-E
,这将确保我们找到H
而不是E
。
将--topo-order
添加到rev-list命令也是一个好主意,因为否则这些提交会按提交日期顺序列出,如果日期/时间被搞砸了在制作存储库时涉及的计算机中,提交可能以错误的顺序列出。
还有--ancestry-path
选项,在某些情况下很有用(可能不适用于您自己的情况):它确保git rev-list
仅列出后代的提交..操作的左侧。你可以在不需要--first-parent
的地方使用它,例如:
...--o--*--A--B--C
\ \ \
D--E--F--G--H <-- branch
如果我们想要提交&#34;三个步骤&#34;在标记提交*
之后,可以是C
或G
。使用git rev-list tag..branch
会打印A
到H
的所有内容(按某种顺序排列)。添加--first-parent
会切断G
或 C
- 这两个中只有一个可以是{{1>的第一个父级 - 如果你想看两者,你就不能使用H
。添加--first-parent
会使--ancestry-path
省略git rev-list
;其余的仍将以某种顺序出现。添加D-E-F
将保证--topo-order
倒数第二,B
最后出现(请记住,Git正在倒退),A
和{{1}在他们之前的任何顺序,并C
首先。
这不是一个完整的解决方案,但如果你有一个像这样的分支和合并图,那么就没有完整的解决方案。
无论如何,选择这些选项的一些子集。如果你知道你的图表是第一父母的,那么,例如:
G
将为您提供所需的哈希值。
(对于另一个稍微微妙的技巧,添加H
以从git rev-list --topo-order --first-parent tag..branchname | tail -2 | head -1
反转打印输出顺序,然后使用--reverse
打印第二行。但是,您无法在此处使用git rev-list
的{{1}}标记,因为它会从未反转的列表中计算并停止,而我们我不知道会有多少次提交,我们想要的是次要的,不管多少次。)
答案 1 :(得分:0)