找到git commit来自哪个分支

时间:2010-04-25 01:23:33

标签: git

有没有办法找出一个提交来自哪个分支给它的sha1?

如果您可以使用Ruby Grit告诉我如何实现这一点,那么可以获得奖励。

15 个答案:

答案 0 :(得分:757)

虽然Dav认为信息不是直接存储的,但这并不意味着你无法找到信息。以下是您可以做的一些事情。

查找提交的分支

git branch --contains <commit>

这将告诉您历史记录中具有给定提交的所有分支。显然,如果提交已经合并,这就不那么有用了。

搜索reflogs

如果您在进行提交的存储库中工作,则可以在reflog中搜索该提交的行。超过90天的Reflogs由git-gc修剪,所以如果提交太旧,你将找不到它。也就是说,你可以这样做:

git reflog show --all | grep a871742

找到提交a871742。输出应该是这样的:

a871742 refs/heads/completion@{0}: commit (amend): mpc-completion: total rewrite

表示提交是在分支“完成”上进行的。默认输出显示缩写的提交哈希值,因此请确保不要搜索完整哈希值,否则您将找不到任何内容。

git reflog show实际上只是git log -g --abbrev-commit --pretty=oneline的别名,所以如果你想摆弄输出格式以便为grep提供不同的东西,那就是你的起点!

如果您不在提交提交的存储库中工作,那么在这种情况下您可以做的最好的事情是检查reflog并查找提交何时首次引入您的repo;运气好的话,你拿到了它所承诺的分支。这有点复杂,因为您不能同时同时执行提交树和reflog。您需要解析reflog输出,检查每个哈希是否包含所需的提交。

查找后续合并提交

这是与工作流程相关的,但是如果工作流程很好,则会在开发分支上进行提交,然后将其合并。您可以这样做:

git log --merges <commit>..

查看具有给定提交作为祖先的合并提交。 (如果提交只合并了一次,那么第一个应该是你正在进行的合并;否则你将需要检查一些,我想。)合并提交消息应该包含已合并的分支名称。

如果您希望能够指望这样做,您可能希望使用--no-ff git merge选项来强制创建合并提交,即使在快进的情况下也是如此。 (不要过于急切,如果过度使用,可能会变得模糊不清。)VonC的answer to a related question有助于详细阐述这一主题。

答案 1 :(得分:64)

这个简单的命令就像一个魅力:

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

答案 2 :(得分:44)

2013年12月更新:

sschuberth comments

  

git-what-branch(Perl脚本,见下文)似乎不再维护了    git-when-merged 是用Python编写的替代方案,对我来说效果很好。

它基于“Find merge commit which include a specific commit”。

git when-merged [OPTIONS] COMMIT [BRANCH...]
  

查找提交何时合并到一个或多个分支   找到将COMMIT带入指定BRANCH的合并提交。

     

具体而言,查找包含BRANCH作为祖先的COMMIT的第一父历史记录中最早的提交。


原始答案2010年9月:

Sebastien Douche只是twitted(在此SO回答前16分钟):

  

git-what-branch :了解提交的分支,或者它如何到达命名分支

这是来自Perl scriptSeth Robertson,看起来非常有趣:

  

<强>概要

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
   [...]
  

该程序没有考虑采摘感兴趣的提交的效果,只考虑合并操作。

答案 3 :(得分:27)

例如,发现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

<强> UPD
或者只是一个命令:

git log c0118fa..HEAD --ancestry-path --merges --oneline --color | tail -n 1

答案 4 :(得分:8)

git branch --contains <ref>是最明显的“瓷器”命令。如果你想用“plumbing”命令做类似的事情:

COMMIT=$(git rev-parse <ref>) # expands hash if needed
for BRANCH in $(git for-each-ref --format "%(refname)" refs/heads); do
  if $(git rev-list $BRANCH | fgrep -q $COMMIT); then
    echo $BRANCH
  fi
done

(来自this SO answer的交叉路口)

答案 5 :(得分:4)

穷人的选择是在HEAD上使用the tool tig 1 ,搜索提交,然后直观地跟踪该提交中的行,直到可以看到合并提交。默认合并消息应指定将哪些分支合并到以下位置:)

  

1 Tig是git的基于ncurses的文本模式界面。它的功能   主要作为Git存储库浏览器,但也可以协助分段   在块级别提交更改,并充当来自的输出的寻呼机   各种Git命令。

答案 6 :(得分:3)

作为一项实验,我做了一个post-commit钩子,它在提交元数据中存储有关当前检出的分支的信息。我还稍微修改了gitk以显示该信息。

您可以在此处查看:https://github.com/pajp/branch-info-commits

答案 7 :(得分:2)

我处理相同的问题(詹金斯多分支管道)-仅提交信息,并尝试查找此提交最初来自的分支名称。它必须适用于远程分支,没有可用的本地副本。

这就是我的工作方式

git rev-parse HEAD | xargs git name-rev | cut -d' ' -f2 | sed 's/remotes\/origin\///g'

(可选)您可以剥离输出:

$headers = array(
'Accept:application/json'
);

$req_response = Curl::to("http://apiv2.jne.co.id:10102/thecore/insert")
->withData($data)
->withHeaders($headers)
->withContentType('application/json')
->asJson()
->withResponseHeaders()
->returnResponseObject()
->post();

答案 8 :(得分:2)

khichar.anil covered大部分都是他的答案。

我只是添加了一个将从修订名称列表中删除标记的标志。这给了我们:

git name-rev --name-only --exclude=tags/* $SHA

答案 9 :(得分:0)

如果OP正在尝试确定创建特定提交时分支遍历的历史(“找出提交来自给定sha1的分支”),那么没有reflog在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;

输出显示没有任何方法可以知道带有“添加f1”的提交是来自远程clone / 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

答案 10 :(得分:0)

TL; DR:

如果您关心shell退出状态,请使用以下内容:

  • branch-current-当前分支的名称
  • branch-names-清除分支名称(每行一个)
  • branch-name-确保仅从branch-names返回一个分支

branch-namebranch-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
  • 输出到STDOUT
  • 退出值为0

可以通过多个分支访问

% git branch-name 4bc6188
Multiple branches:
attempt-extract
master%                                                                                                                                                                                                            
% echo $?
1
  • 输出到STDERR
  • 退出值为1

由于退出状态,可以安全地建立这些状态。例如,获取用于提取的遥控器:

remote-fetch = !"branch=$(git branch-name \"$1\") && git config branch.\"$branch\".remote || echo origin #"

答案 11 :(得分:0)

我认为有人应该面临找不到分支的相同问题,尽管它实际上存在于一个分支中。

您最好首先拉动:

git pull --all

然后执行分支搜索:

git name-rev <SHA>

或:

git branch --contains <SHA>

答案 12 :(得分:0)

我尝试了上述所有解决方案,但没有一个对我有用。

这是迄今为止唯一对我有用的方法(假设 HEAD 处于合理的位置):

git log --branches --source | grep <sha>

#or if you also care about remotes
git log --branches --remotes --source | grep <sha>

分支名称应在行尾。

来自documentation

<块引用>

--来源

打印在命令行上给出的每次提交的引用名称。

所以这可能会根据 HEAD 的位置而改变,但对我来说,将 HEAD 放在我的主分支上的最新提交中产生了我预期的结果。

使用 gitk --all 进行目视检查也可能会有所帮助。每个提交都有一个“分支”字段,但它显示“可以到达”该提交的所有分支,而不一定是该提交“打开”的分支。 See here

答案 13 :(得分:-1)

查找本地分支

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'

答案 14 :(得分:-4)

除了搜索所有树之外,直到找到匹配的哈希,没有。