Eri*_*fer 35 git version-control
如果我从多个分支中挑选,是否有一种简单的方法来确定提交的来源(例如原始提交的sha)?
示例:
- 在主分支
- 来自开发分支的樱桃选择提交A
- A在主分支处变为D.
之前:
* B (master) Feature Y
| * C (dev) Feature Z
| * A Feature X
|/
* 3
* 2
* 1
Run Code Online (Sandbox Code Playgroud)
后:
* D (master) Feature X
* B Feature Y
| * C (dev) Feature Z
| * A Feature X
|/
* 3
* 2
* 1
Run Code Online (Sandbox Code Playgroud)
是否有可能弄清楚D是从A中挑选出来的(除了搜索提交消息)?
编辑:
虽然我会使用daggy-fixes(请参阅VonCs回答)我接受了Chris Johnsens的回答,因为它更接近实际问题.多谢你们.
Chr*_*sen 38
默认情况下,有关原始"cherry"提交的信息不会记录为新提交的一部分.
如果您可以强制使用特定的工作流程/选项,
git cherry-pick有以下-x选项:
记录提交时,在原始提交消息后附加一个注释,指示从哪个提交中挑选出此更改.
如果您不能使用该选项依赖樱桃采摘器,这显然是无用的.此外,由于记录的信息只是纯文本 - 而不是Git所涉及的实际参考 - 即使您使用-x,您仍然必须采取措施以确保原始提交保持活动(例如,是标签的DAG或非倒带分支).
如果你可以将你的搜索限制在历史DAG的两个特定分支,那么git cherry可以找到"未挑出"和"挑选"的樱桃.
注意:此命令(以及相关的git patch-id)只能识别在没有额外更改的情况下单独挑选的无冲突樱桃.如果在挑选樱桃时发生冲突(例如,您必须稍微修改它以使其适用),或者您使用-n/ --no-commit进行额外更改(例如,在单次提交中多个樱桃),或者提交的内容被重写在选择之后,您将不得不依赖提交消息比较(或者-x如果记录了信息).
git cherry并不是真正用于识别采摘樱桃的来源,但我们可以稍微滥用它来识别单个樱桃对.
鉴于以下历史DAG(如原始海报的例子):
1---2---3---B---D master
\
A---C dev
# D is a cherry-picked version of C
Run Code Online (Sandbox Code Playgroud)
你会看到这样的东西:
% git cherry master dev
+ A
- C
% git cherry dev master
+ B
- D
Run Code Online (Sandbox Code Playgroud)
(A,B,C和D是实际输出中的完整SHA-1哈希值)
由于我们-在每个列表中看到一个樱桃(线条),它们必须形成樱桃对.D是从C中挑选的樱桃(反之亦然;虽然提交日期可能有所帮助,但您无法单独告诉DAG).
如果您正在处理多个潜在的樱桃,您将不得不"自己动手"程序来进行映射.在具有关联数组,散列,字典或等效语言的任何语言中,代码都应该很容易.在awk中,它可能看起来像这样:
match_cherries() {
a="$(git rev-parse --verify "$1")" &&
b="$(git rev-parse --verify "$2")" &&
git rev-list "$a...$b" | xargs git show | git patch-id |
awk '
{ p[$1] = p[$1] " " $2 }
END {
for (i in p) {
l=length(p[i])
if (l>41) print substr(p[i],2,l-1)
}
}'
}
match_cherries master dev
Run Code Online (Sandbox Code Playgroud)
有一个扩展的例子,有两个采摘樱桃:
1---2---3---B---D---E master
\
A---C dev
# D is a cherry-picked version of C
# E is a cherry-picked version of A
Run Code Online (Sandbox Code Playgroud)
输出可能如下所示:
match_cherries master dev
D C
E A
Run Code Online (Sandbox Code Playgroud)
(A,C,D和E是实际输出中的完整SHA-1哈希值)
这告诉我们C和D代表相同的变化,E和A代表相同的变化.和以前一样,除非你还考虑(例如)每次提交的提交日期,否则无法分辨哪一对是"第一对".
如果您的樱桃没有被挑选-x,或者它们是"脏"的(有冲突或其他更改添加到它们(即--no-commit加上额外的更改,或与git commit --amend其他"历史重写"机制)),那么你可能不得不跌倒回到较少可靠的比较提交消息的技术.
如果您可以找到一些可能对提交唯一的提交消息并且不太可能在提交中产生更改,那么此技术最有效.最有效的位将取决于项目中使用的提交消息的样式.
一旦你选择了消息的"识别部分",就可以使用git log来查找提交(也在Jefromi的答案中演示).
git log --grep='unique part of the commit message' dev...master
Run Code Online (Sandbox Code Playgroud)
参数to --grep实际上是一个正则表达式,因此您可能需要转义任何regexp元字符([]*?.\).
如果您不确定哪个分支可能包含原始提交和新提交,您可以使用--allJefromi显示.
Von*_*onC 10
如果我按照你的图表,你想知道你是否可以确定,而不是D(不是B)是采摘樱桃的结果.
理论上,如" 如何列出包含给定提交的git分支? "中所示,如果D实际上是与A相同的提交(SHA1),则可以搜索提交:
git branch --contains <commit>
Run Code Online (Sandbox Code Playgroud)
但正如Jefromi评论的那样,D在这种情况下不能拥有相同的SHA1.
这留下了寻找共同提交消息的信息:请参阅Jefromi的回答.
正如Ken Bloom在问题的评论中提到的那样,对于这样的本地樱桃采摘,一种daggy-fix技术(如单调或mercurial)更合适,因为它会留下合并的清晰痕迹.
Daggy修复意味着使用而不是丢失祖先图中的错误和修复之间的真正起源和关系.
由于[Git]提供了在任何修订版本之上进行提交的能力,从而产生了一个小的匿名分支,一个可行的樱桃选择方法如下:
- 使用bisect来识别出现错误的修订版;
- 查看该修订;
- 修复bug;
- 并将修复程序作为引入该错误的修订版的子项提交.
这个新的变化可以很容易地合并到任何有原始bug的分支中,而不需要任何粗略的挑选樱桃的滑稽动作.
它使用修订控制工具的常规合并和冲突解决机制,因此它比采摘樱桃更可靠(其执行几乎总是一系列奇怪的黑客攻击).
(这里是Mercurial图,但很容易应用于Git)
一直做daggy修复不适合每个人.
在引入错误的修订版中直接开发修复程序并不总是那么容易.
- 也许直到其他一些更新的代码以暴露bug的方式使用它时才发现这个bug; 如果没有其他代码,很难调试并找到修复程序.
- 或许当时还没有实现修复的重要性或范围.
有关daggy-fix的更多信息,另请参阅此文章:
这种恢复历史以修复错误,然后将修复程序合并到现代分支中的技术被Monotone的作者称为"daggy fixes",Monotone是一个有影响力的分布式修订控制系统.
这些修复被称为daggy,因为它们利用项目的历史结构为有向无环图或dag.
虽然这种方法可以与Subversion一起使用,但与分布式工具相比,它的分支是重量级的,这使得daggy-fix方法不太实用.这强调了一种工具的优势将为其用户带来的技术提供信息的想法.
没有关于原始提交的信息嵌入在新创建的提交中,因此没有直接的方法来判断。您的建议(搜索提交消息)可能是最好的方法 - 这肯定比搜索具有相同差异的提交容易得多:
git log --grep="<commit subject>" --all
Run Code Online (Sandbox Code Playgroud)
除非当然不再可以从分支访问提交......否则你可能想要查看git fsck.
| 归档时间: |
|
| 查看次数: |
13420 次 |
| 最近记录: |