在给定其SHA-1哈希值的情况下,是否有办法找出提交来自哪个分支?
如果您能告诉我如何使用Ruby Grit做到这一点,则可以加分。
在给定其SHA-1哈希值的情况下,是否有办法找出提交来自哪个分支?
如果您能告诉我如何使用Ruby Grit做到这一点,则可以加分。
Answers:
尽管Dav是正确的,即不会直接存储信息,但这并不意味着您永远找不到。这是您可以做的几件事。
git branch -a --contains <commit>
这将告诉您所有在历史记录中具有给定提交的分支。显然,如果提交已被合并,则此功能就没什么用了。
如果您正在其中进行提交的存储库中,则可以在引用日志中搜索该提交的行。超过90天的Reflog会被git-gc删除,因此,如果提交的时间太长,您将找不到它。也就是说,您可以执行以下操作:
git reflog show --all | grep a871742
找到提交a871742。请注意,您必须使用提交的首7位缩写。输出应该是这样的:
a871742 refs/heads/completion@{0}: commit (amend): mpc-completion: total rewrite
指示在分支“完成”上进行了提交。默认输出显示缩写的提交哈希,因此请确保不要搜索完整的哈希,否则将找不到任何内容。
git reflog show
实际上只是它的别名 git log -g --abbrev-commit --pretty=oneline
,因此,如果您想弄乱输出格式以使grep可以使用其他内容,那就是您的起点!
如果您不在进行提交的存储库中工作,那么在这种情况下,您最好的方法是检查reflog,并查找何时首次将提交引入存储库中。运气好的话,您就获得了它所承诺的分支。这有点复杂,因为您不能同时遍历提交树和刷新日志。您需要解析reflog输出,检查每个哈希以查看其是否包含所需的提交。
这是依赖于工作流程的,但是如果工作流程良好,则会在开发分支上进行提交,然后将其合并。您可以执行以下操作:
git log --merges <commit>..
查看具有给定提交作为祖先的合并提交。(如果提交只被合并了一次,那么我想,第一个应该是您要进行的合并;否则,您必须检查一下。)合并提交消息应包含已合并的分支名称。
如果您希望能够这样做,那么即使在快进情况下,也可能希望使用该--no-ff
选项git merge
来强制执行合并提交创建。(不过,不要急于求成。如果使用过度,这可能会令人困惑。)VonC对一个相关问题的回答有助于详细说明该主题。
git describe
就足够了,因为(带注释的)标签可以被视为比分支更重要。
--no-ff
选项来确保始终存在合并提交,因此您可以始终跟踪给定提交向主提交的合并的路径。
-a
标志添加到第一个命令,例如git branch -a --contains <commit>
-r
。
merge --no-ff
在合并时可靠地记录分支名称。但是否则,请将分支名称视为临时的短标签,并将描述提交为永久的短标签。“在开发过程中,我们用什么简称?” 真的不应该像“此提交做什么”这样重要的问题吗?
这个简单的命令就像一个魅力:
git name-rev <SHA>
例如(其中test-branch是分支名称):
git name-rev 651ad3a
251ad3a remotes/origin/test-branch
即使这样也适用于复杂的场景,例如:
origin/branchA/
/branchB
/commit<SHA1>
/commit<SHA2>
这里git name-rev commit<SHA2>
返回branchB。
git name-rev --name-only <SHA>
对于仅获取分支名称更有用。我的问题...在任何情况下都可以返回多个分支吗?
2013年12月更新:
git-what-branch
(Perl脚本,请参见下文)似乎不再被维护。git-when-merged
是用Python编写的替代方法,对我来说效果很好。
它基于“ 查找包含特定提交的合并提交 ”。
git when-merged [OPTIONS] COMMIT [BRANCH...]
查找何时将提交合并到一个或多个分支中。
查找带入COMMIT
指定BRANCH 的合并提交。具体来说,在
BRANCH
包含其COMMIT
祖先的第一对父代历史记录中查找最旧的提交。
2010年9月的原始答案:
塞巴斯蒂安·杜切杜什(刚刚被抽搐了(在此回答之前16分钟):
git-what-branch:发现提交在哪个分支上,或如何到达命名分支
概要
git-what-branch [--allref] [--all] [--topo-order | --date-order ]
[--quiet] [--reference-branch=branchname] [--reference=reference]
<commit-hash/tag>...
总览
告诉我们(默认情况下)最早的提交和合并因果路径,以使请求的提交进入命名分支。如果直接在命名分支上进行提交,则显然是最早的路径。
所谓最早的因果路径,是指按照提交时间最早并入命名分支的路径(除非
--topo-order
指定)。性能
如果许多分支(例如数百个)包含提交,则系统可能需要较长时间(对于Linux树中的特定提交,探索分支需要8秒,但是有200多个候选分支)来追踪路径每次提交。
选择一个特定的--reference-branch --reference tag
要检查将快数百倍(如果您有数百个候选分支)。例子
# git-what-branch --all 1f9c381fa3e0b9b9042e310c69df87eaf9b46ea4
1f9c381fa3e0b9b9042e310c69df87eaf9b46ea4 first merged onto master using the following minimal temporal path:
v2.6.12-rc3-450-g1f9c381 merged up at v2.6.12-rc3-590-gbfd4bda (Thu May 5 08:59:37 2005)
v2.6.12-rc3-590-gbfd4bda merged up at v2.6.12-rc3-461-g84e48b6 (Tue May 3 18:27:24 2005)
v2.6.12-rc3-461-g84e48b6 is on master
v2.6.12-rc3-461-g84e48b6 is on v2.6.12-n
[...]
该程序不考虑选择感兴趣的提交的影响,仅考虑合并操作。
git-what-branch
似乎不再维护了。git-when-merged是用Python编写的替代方法,对我来说很好用。
例如,要查找该c0118fa
提交来自redesign_interactions
:
* ccfd449 (HEAD -> develop) Require to return undef if no digits found
* 93dd5ff Merge pull request #4 from KES777/clean_api
|\
| * 39d82d1 Fix tc0118faests for debugging debugger internals
| * ed67179 Move &push_frame out of core
| * 2fd84b5 Do not lose info about call point
| * 3ab09a2 Improve debugger output: Show info about emitted events
| * a435005 Merge branch 'redesign_interactions' into clean_api
| |\
| | * a06cc29 Code comments
| | * d5d6266 Remove copy/paste code
| | * c0118fa Allow command to choose how continue interaction
| | * 19cb534 Emit &interact event
您应该运行:
git log c0118fa..HEAD --ancestry-path --merges
向下滚动以查找最后的合并提交。这是:
commit a435005445a6752dfe788b8d994e155b3cd9778f
Merge: 0953cac a06cc29
Author: Eugen Konkov
Date: Sat Oct 1 00:54:18 2016 +0300
Merge branch 'redesign_interactions' into clean_api
更新资料
或者只是一个命令:
git log c0118fa..HEAD --ancestry-path --merges --oneline --color | tail -n 1
git merge -m"Any String Here"
会掩盖源分支目标和目标分支信息。
Merge: f6b70fa d58bdcb
。您可以像这样命名合并提交。我不会
khichar.anil覆盖在他的回答中大部分内容。
我只是添加了一个将从修订名称列表中删除标记的标志。这给我们:
git name-rev --name-only --exclude=tags/* $SHA
作为一个实验,我做了一个提交后钩子,该钩子将有关当前签出的分支的信息存储在提交元数据中。我还稍微修改了gitk以显示该信息。
您可以在这里查看:https : //github.com/pajp/branch-info-commits
如果OP试图确定创建特定提交时分支所遍历的历史记录(“在给定其SHA-1散列值的情况下查找提交来自哪个分支”),那么没有引用日志,就不会有任何引用Git对象数据库中的记录,显示了什么命名分支绑定到什么提交历史记录。
(我将其发布为答复评论的答案。)
希望此脚本可以说明我的观点:
rm -rf /tmp/r1 /tmp/r2; mkdir /tmp/r1; cd /tmp/r1
git init; git config user.name n; git config user.email e@x.io
git commit -m"empty" --allow-empty; git branch -m b1; git branch b2
git checkout b1; touch f1; git add f1; git commit -m"Add f1"
git checkout b2; touch f2; git add f2; git commit -m"Add f2"
git merge -m"merge branches" b1; git checkout b1; git merge b2
git clone /tmp/r1 /tmp/r2; cd /tmp/r2; git fetch origin b2:b2
set -x;
cd /tmp/r1; git log --oneline --graph --decorate; git reflog b1; git reflog b2;
cd /tmp/r2; git log --oneline --graph --decorate; git reflog b1; git reflog b2;
输出显示缺少任何方法来知道带有'Add f1'的提交是来自远程克隆/ tmp / r2的分支b1还是b2。
(此处输出的最后几行)
+ cd /tmp/r1
+ git log --oneline --graph --decorate
* f0c707d (HEAD, b2, b1) merge branches
|\
| * 086c9ce Add f1
* | 80c10e5 Add f2
|/
* 18feb84 empty
+ git reflog b1
f0c707d b1@{0}: merge b2: Fast-forward
086c9ce b1@{1}: commit: Add f1
18feb84 b1@{2}: Branch: renamed refs/heads/master to refs/heads/b1
18feb84 b1@{3}: commit (initial): empty
+ git reflog b2
f0c707d b2@{0}: merge b1: Merge made by the 'recursive' strategy.
80c10e5 b2@{1}: commit: Add f2
18feb84 b2@{2}: branch: Created from b1
+ cd /tmp/r2
+ git log --oneline --graph --decorate
* f0c707d (HEAD, origin/b2, origin/b1, origin/HEAD, b2, b1) merge branches
|\
| * 086c9ce Add f1
* | 80c10e5 Add f2
|/
* 18feb84 empty
+ git reflog b1
f0c707d b1@{0}: clone: from /tmp/r1
+ git reflog b2
f0c707d b2@{0}: fetch origin b2:b2: storing head
git log 80c10e5..HEAD --ancestry-path --merges --oneline --color | tail -n 1
和git log 086c9ce..HEAD --ancestry-path --merges --oneline --color | tail -n 1
命令是什么?
$ git log HEAD^1..HEAD --ancestry-path --merges --oneline --color | tail -n 1
哪个产生376142d merge branches
和$ git log HEAD^2..HEAD --ancestry-path --merges --oneline --color | tail -n 1
哪个产生376142d merge branches
-显示合并提交摘要,在创建合并时可以覆盖(如我所断言的)摘要,这可能会使合并的分支历史模糊。
如果您关心Shell退出状态,请使用以下内容:
branch-current
-当前分支的名称branch-names
-干净的分支名称(每行一个)branch-name
-确保仅从中返回一个分支 branch-names
双方branch-name
并branch-names
接受提交作为参数,并默认 HEAD
如果没有给出。
branch-current = "symbolic-ref --short HEAD" # https://stackoverflow.com/a/19585361/5353461
branch-names = !"[ -z \"$1\" ] && git branch-current 2>/dev/null || git branch --format='%(refname:short)' --contains \"${1:-HEAD}\" #" # https://stackoverflow.com/a/19585361/5353461
branch-name = !"br=$(git branch-names \"$1\") && case \"$br\" in *$'\\n'*) printf \"Multiple branches:\\n%s\" \"$br\">&2; exit 1;; esac; echo \"$br\" #"
% git branch-name eae13ea
master
% echo $?
0
0
。% git branch-name 4bc6188
Multiple branches:
attempt-extract
master%
% echo $?
1
1
。由于存在退出状态,因此可以安全地建立这些状态。例如,要获取用于获取的遥控器:
remote-fetch = !"branch=$(git branch-name \"$1\") && git config branch.\"$branch\".remote || echo origin #"
查找本地分支:
grep -lR YOUR_COMMIT .git/refs/heads | sed 's/.git\/refs\/heads\///g'
查找远程分支:
grep -lR $commit .git/refs/remotes | sed 's/.git\/refs\/remotes\///g'