我要创建未合并分支的一些代码审查。
在寻找解决方案,让我们不要去当地的分支方面的问题,因为这将在服务器上运行; 届时会有产地偏远,我会一直运行混帐其他命令前取起源命令,当我们谈论的分支,我们将把产地/分支名称 。
如果设置为简单,源自高手继续以自己的方式每个分支,我们可以只运行:
git rev-list origin/branch-name --not origin/master --no-merges
每个分支未合并,并将所得的提交添加到每个分支每次审查。
当有2-3个分支机构和工作之间的合并继续就其中一些问题就出现了。 正如我所说的,每个分支我想创建代码审查方案和我不希望包括在多个评论提交。
主要的问题,减少对寻找原分公司为每个提交。
或者把它简单...找出所有未合并的提交由他们最有可能被创建的分支进行分组。
让我们关注一个简单的例子:
* b4 - branch2's head
* | a4 - branch1's head
| * b3
* | merge branch2 into branch1
* |\ | m3 - master's head
| * \| a3
| | |
| | * b2
| * | merge master into branch1
* /| | m2
|/ | * merge branch1 into branch2
| * /| a2
| |/ |
| | * b1
| | /
| |/
| /|
|/ |
| * a1
* / m1
|/
|
* start
和我想要得到的是:
- BRANCH1:A1,A2,A3,A4
- BRANCH2:B1,B2,B3,B4
我迄今发现的最好的解决方法是运行:
git show-branch --topo-order --topics origin/master origin/branch1 origin/branch2
并解析结果:
* [master] m3
! [branch1] a4
! [branch2] b4
---
+ [branch2] b4
+ [branch2^] b3
+ [branch1] a4
++ [branch2~2] b2
-- [branch2~3] Merge branch 'branch1' into branch2
++ [branch2~4] b1
+ [branch1~2] a3
+ [branch1~4] a2
++ [branch1~5] a1
*++ [branch2~5] m1
输出解释是这样的:
- 前n行是N个分支分析
- 一个符合----
- 一条线的每个与所述n个压痕字符加(或减在合并的情况下提交)提交如果提交是在n个分支。
- 最后一行是分析所有分支的合并基础
对于点3.提交名称解析开始用树枝名称,从我所看到的,这个分支对应于提交创建时,可能是由一父促进路径到达分支。
正如我在合并提交不感兴趣,我会忽略它们。
然后我会分析每个分支通道提交,以获得他们的哈希与REV-解析。
我该如何处理这种情况?
存储库可以与被克隆--mirror
它创建一个可以用作原始资源库的一面镜子,可以用更新的纯仓库git remote update --prune
后,所有的标签应此功能被删除。
我实现了这种方式:
1.获得分支的列表不合并到主
git branch --no-merged master
2.每个分支获得不是在主分支中的分支上的修订列表
git rev-list branch1 --not master --no-merges
如果该列表是空的,从分支机构的列表中删除分支
3.每个修订,确定与原分公司
git name-rev --name-only revisionHash1
和匹配的正则表达式^([^\~\^]*)([\~\^].*)?$
。 所述第一图案是分支名,第二个是将分支的相对路径。
如果发现分支名不等于初始分支,从列表中删除修订。
最后我得到的树枝,为他们每个人的提交列表清单。
一些bash的研究后,是可以做到的一切与一个行:
git rev-list --all --not master --no-merges | xargs -L1 git name-rev | grep -oE '[0-9a-f]{40}\s[^\~\^]*'
结果是形式的输出
hash branch
它可以读取,解析,有序,组或什么的。
如果我抓住你的问题空间,认为你可以使用--sha1名
混帐秀分支--topo阶--topics --sha1名产地/产地主/ BRANCH1产地/ BRANCH2
列出你所感兴趣的东西,然后通过运行混帐东西分支的提交
混帐东西分支 :发现是基于哪一个分支提交,不然怎么到了一个名为分支。 这是一个Perl脚本从塞思·罗伯逊
并格式化报告适合您的需求?
没有正确回答这个问题,因为它是尚未。
提交历史仅仅是一个有向非循环图(DAG),它是通常不可能确定在DAG中任意两个节点之间的语义关系,除非节点被充分地标记。 除非你能保证你的榜样图提交信息遵循可靠,机器可分析的模式,提交没有充分标记,这是不可能自动识别你所感兴趣的提交,无需额外的上下文(例如,保证您的开发人员都遵循某些最佳实践)。
下面是我的意思的例子。 你说,提交a1
与相关branch1
,但是这不能只是看你的例子图的节点肯定地确定。 这有可能是很久以前你的榜样库的历史是这样的:
* merge branch1 into branch2 - branch2's head
|\
_|/
/ * b1
| |
| |
_|_/
/ |
| * a1
* / m1
|/
|
* start - master's head
需要注意的是branch1
甚至没有在上面的图中还不存在。 以上图表可以从下面的事件序列出现了:
-
branch2
在创建start
在共享存储库 - 用户#1创建
a1
在他/她的本地branch2
分公司 - 同时,用户#2创建
m1
和b1
对他/她的本地branch2
分公司 - 用户#1推他/她的本地
branch2
分公司共享资源库,从而导致branch2
裁判的共享资源库,以指向a1
- 用户#2试图推动他/她的本地
branch2
分公司共享资源库,但这种失败与非快速向前错误( branch2
当前指向a1
,不能快进至b1
) - 用户#2运行
git pull
,合并a1
到b1
- 用户#2运行
git commit --amend -m "merge branch1 into branch2"
对于一些无法解释的原因 - 用户#2推压,并共享存储库历史最终看起来像上述DAG
一段时间后,用户#1创建branch1
关闭的a1
和创造a2
,而用户#2快进合并m1
到master
,从而产生以下提交历史:
* merge a1 into b1 - branch2's head
* |\ a2 - branch1's head
| _|/
|/ * b1
| |
| |
_|_/
/ |
| * a1
* / m1 - master's head
|/
|
* start
鉴于这一系列事件在技术上是可能的(虽然不太可能),怎么能一个人更不用说Git的告诉你哪些承诺“属于”哪个分支?
解析合并提交信息
如果你能保证用户不会改变合并提交消息(他们总是接受Git的默认值),而Git有没有,今后也不会改变默认合并提交信息的格式,然后将合并提交的提交信息可以作为一个线索即a1
开始了对branch1
。 你必须编写一个脚本来分析提交信息,有没有简单的Git单行为你做到这一点。
如果梅杰斯是始终有意
另外,如果你的开发人员遵循最佳实践(每个合并是故意的,是指在一个不同名称的分支带来,导致没有一个仓库那些愚蠢的合并提交内容创建git pull
),而你不感兴趣,从该提交填妥的子分支,那么你很感兴趣的是提交的第一父路径上。 如果你知道哪个分支是您所分析的分支的父母,你可以做到以下几点:
git rev-list --first-parent --no-merges parent-branch-ref..branch-ref
该命令列出了从到达的提交的SHA1标识branch-ref
排除从到达的提交parent-branch-ref
和被从子分支合并的提交。
在你上面的例子图,假设母订单是由您的注解,而不是通过进入合并行的顺序确定提交, git rev-list --first-parent --no-merges master..branch1
将打印的SHA1标识符提交A4,A3,A2,A1和(按顺序;使用--reverse
如果你想以相反的顺序),和git rev-list --first-parent --no-merges master..branch2
将打印SHA1标识符提交B4,B3,B2和B1(再次,按照这个顺序)。
如果分行有明确父/子关系
如果你的开发人员不遵循最佳做法和你的分支与创建的那些愚蠢的合并散落git pull
(或等效的操作),但你必须清楚的父/子分支的关系,然后写一个脚本来执行下面的算法可用于工作您:
找到所有从不包括其母公司分支机构,其母公司的母公司分支机构,其母公司的母公司的分支机构等,所有提交感兴趣的分支提交可达,并保存结果。 例如:
git rev-list master..branch1 >commit-list
执行相同的所有孩子,孙子等感兴趣的分支的分支。 例如,假设branch2
被认为是一个孩子branch1
:
git rev-list ^master ^branch1 branch2 >commits-to-filter-out
从步骤#1中的结果筛选出的步骤#2中的结果。 例如:
grep -Fv -f commits-to-filter-out commit-list
这种方法的问题是,一旦一个子分支合并到母公司,这些提交被认为是即使在子分支发展下去父的一部分。 虽然这种语义上是有道理的,它不会产生你说你想要的结果。
一些最佳实践
下面是一些最佳实践,使这个特殊的问题更容易在未来解决。 如果不是所有的这些都可以通过在共享存储库巧用钩子的执行。
- 每个分支只有一个任务。 多任务是禁止的。
- 决不允许开发继续对孩子的分支,一旦它已经被合并到其父。 合并意味着一个任务已经完成,故事的结尾。 答案预期的问题:
- 问:如果我发现什么的子分支中的错误? 答:开始一个新的分支离开父母的。 不要继续对孩子的分支发展。
- 问:如果新功能尚未做些什么? 答:那你为什么合并分支? 也许你合并一个完整的子任务; 如果是这样,其余的子任务应该继续自己的分支父分支。 不要继续对孩子的分支发展。
- 禁止使用的
git pull
- 除非所有的子分支已合并到其子分支不能合并到母公司。
- 如果分支机构不具有任何孩子分支机构,考虑与合并前基础重建它到父分支
--no-ff
。 如果它确实有孩子的分支,你仍然可以变基,但请保留--no-ff
的孩子分支的合并(这是棘手比它应该是)。 - 合并母公司分支到子分支经常使合并冲突更容易解决。
- 避免直接合并祖父母分支到其孙子分支合并到第一个孩子,那么孩子融入孙子。
如果所有的开发人员遵循这些规则,那么一个简单的:
git rev-list --first-parent --no-merges parent-branch..child-branch
是所有你需要看到该分支减去其子分支提出的提交所做的提交。
我建议做那种你所描述的方式。 不过,我会在输出工作git log --format="%H:%P:%s" ^origin/master origin/branch1 origin/branch2
,所以你可以做的更好树行走。
- 从输出构建一个适当的树状结构,标志着父母和孩子。
- 开始从头部(从他们的SHA走
git rev-parse
)。 马克每一个承诺与你来自的头部,其距离的名字。 - 对于不先父步骤(合并的其他部分),我会添加100向距离。
- 如果你遇到一个合并提交,检查是怎么说哪个分支并入其中。 以下两个父链接时,使用这样的信息:如果分支的解析名字你会不符合当前的HEAD,增加10000至距离。
- 对于双方父母:你现在知道他们的名字。 加入他们的孩子,他们是第一次,父母的字典:
commit -> known-name
。
- 把你的已知命名的提交字典,并开始走上了树(朝孩子,不是父母)。 从合并,到分公司的距离10000。减去。 虽然这样做步行至不会去犯,你是不是第一次,家长,一旦你打一个分支点停止(提交有两个孩子)。 如果你打你的分支头一个也停止。
现在,每一个你的提交,你将有距离值的列表(可能是负的)到您的分支头。 对于每一个承诺,用最少的距离的分支是一个最有可能产生的承诺。
如果你有时间,你可能会想走路的整个历史,然后掌握。减去的历史 - 如果你的分支之前已合并到主可能给稍微好一点的结果。
无法抗拒:由Python脚本,做什么,我描述。 但有一个变化:每一步正常,距离不增加,反而下降。 这有一个合并点后活得更长分支首选的效果,我个人更喜欢。 在这里,它是: https://gist.github.com/Chronial/5275577
使用方法:只需运行git-annotate-log.py ^origin/master origin/branch1 origin/branch2
检查结果的质量(将输出带有注释的git的日志树)。
文章来源: How to find all unmerged commits in master grouped by the branches they were created in?