Git 2.36 提出了一个更简单的命令:
(branch_A_tag)
|
--X--A--B--C--D--F (master)
\ / \ /
\ / \ /
G--H--I--J (branch A)
vonc@vclp MINGW64 ~/git/tests/branchOrigin (branch_A)
git log -1 --decorate --oneline \
$(git rev-parse \
$(git rev-list --exclude-first-parent-only ^main branch_A| tail -1)^ \
)
80e8436 (tag: branch_A_tag) A - Work in branch main
git rev-list --exclude-first-parent-only ^main branch_A
会给你 J -- I -- H -- G
tail -1
会给你 G
git rev-parse G^
会给你它的第一个父节点: A
或者 branch_A_tag
使用测试脚本:
mkdir branchOrigin
cd branchOrigin
git init
git commit --allow-empty -m "X - Work in branch main"
git commit --allow-empty -m "A - Work in branch main"
git tag branch_A_tag -m "Tag branch point of branch_A"
git commit --allow-empty -m "B - Work in branch main"
git switch -c branch_A branch_A_tag
git commit --allow-empty -m "G - Work in branch_A"
git switch main
git merge branch_A -m "C - Merge branch_A into branch main"
git switch branch_A
git commit --allow-empty -m "H - Work in branch_A"
git merge main -m "I - Merge main into branch_A"
git switch main
git commit --allow-empty -m "D - Work in branch main"
git merge branch_A -m "F - Merge branch_A into branch main"
git switch branch_A
git commit --allow-empty -m "J - Work in branch_A branch"
这将给你:
vonc@vclp MINGW64 ~/git/tests/branchOrigin (branch_A)
$ git log --oneline --decorate --graph --branches --all
* a55a87e (HEAD -> branch_A) J - Work in branch_A branch
| * 3769cc8 (main) F - Merge branch_A into branch main
| |\
| |/
|/|
* | 1b29fa5 I - Merge main into branch_A
|\ \
* | | e7accbd H - Work in branch_A
| | * 87a62f4 D - Work in branch main
| |/
| * 7bc79c5 C - Merge branch_A into branch main
| |\
| |/
|/|
* | 0f28c9f G - Work in branch_A
| * e897627 B - Work in branch main
|/
* 80e8436 (tag: branch_A_tag) A - Work in branch main
* 5cad19b X - Work in branch main
这是什么:
(branch_A_tag)
|
--X--A--B--C--D--F (master)
\ / \ /
\ / \ /
G--H--I--J (branch A)
在 Git 2.36 (Q2 2022) 中,"
git log
"
(man) 和相关工具学会了一个选项
--exclude-first-parent-only
,它可以仅沿着第一父节点链传播 UNINTERESTING 标志,就像
--first-parent
选项只显示缺少 UNINTERESTING 标志的提交记录沿着第一父节点链。
请查看提交9d505b7(2022年1月11日)由Jerry Zhang (jerry-skydio
)提交。
(由Junio C Hamano -- gitster
--合并于提交708cbef,2022年2月17日)
git-rev-list
:添加--exclude-first-parent-only标志
签名作者:Jerry Zhang
It is useful to know when a branch first diverged in history from some integration branch in order to be able to enumerate the user's local changes.
However, these local changes can include arbitrary merges, so it is necessary to ignore this merge structure when finding the divergence point.
In order to do this, teach the "rev-list
" family to accept "--exclude-first-parent-only
", which restricts the traversal of excluded commits to only follow first parent links.
-A-----E-F-G--main
\ / /
B-C-D--topic
In this example, the goal is to return the set {B, C, D
} which represents a topic branch that has been merged into main
branch.
git rev-list topic ^main
(man) will end up returning no commits since excluding main
will end up traversing the commits on topic
as well.
git rev-list --exclude-first-parent-only topic ^main
(man) however will return {B, C, D}
as desired.
Add docs for the new flag, and clarify the doc for --first-parent
to indicate that it applies to traversing the set of included commits only.
rev-list-options
现在在其手册页面中包括:
--first-parent
在查找要包含的提交时,仅跟随第一个父提交。
当查看特定主题分支的演变时,此选项可以提供更好的概述,因为合并到主题分支的合并通常只涉及不时地调整更新的上游,而此选项允许您忽略由此类合并带入历史记录的单个提交。
rev-list-options
现在在其手册页面中包括:
--exclude-first-parent-only
当查找要排除的提交(使用 '{caret}')时,只追踪第一个父提交。
这可用于确定主题分支中从分叉点开始的更改集,因为任意合并都可以是有效的主题分支更改。
正如anarcat在评论中所指出的,如果你的分支不是从master
派生而来,而是从main
、prod
或其他任何分支派生而来,你可以使用以下命令:
git for-each-ref --merged="$local_ref" --no-contains="$local_ref" \
--format="%(refname:strip=-1)" --sort='-*authordate' refs/heads
philb 在 评论中 也提到了 --boundary
选项 (输出排除边界提交。边界提交以-
为前缀):
git rev-list --exclude-first-parent-only --boundary ^main branch_A | tail -1
to get A
directly, without needing an additional git rev-parse G^
git rev-parse $(git rev-list --exclude-first-parent-only ^main branch_A| tail -1)^
。请参见下面的答案。 - VonC