想象一下下面的历史:

       c---e---g--- feature
      /         \
-a---b---d---f---h--- master

我怎么能找到当提交“c”已合并到主(即,找到合并提交“h”)?


当前回答

你可以尝试这样做。这个想法是遍历所有的合并提交,看看是否可以从其中一个提交“c”到:

$ git log --merges --format='%h' master | while read mergecommit; do
  if git log --format='%h' $mergecommit|grep -q $c; then
    echo $mergecommit;
    break
  fi
done

其他回答

也就是说,总结一下Gauthier的文章:

perl -ne 'print if ($seen{$_} .= @ARGV) =~ /10$/' <(git rev-list --ancestry-path <SHA-1_for_c>..master) <(git rev-list --first-parent <SHA-1_for_c>..master) | tail -n 1

EDIT:因为它使用进程替换“<()”,所以它不兼容POSIX,并且它可能无法与您的shell一起工作。不过,它适用于bash或zsh。

基于Gauthier的回答,我们不需要使用comm来比较列表。因为我们在——ancestry-path中寻找最后一个结果,它也在——first-parent中,我们可以简单地在前者的输出中grep后者:

git rev-list <SHA>..master --ancestry-path | grep -f <(git rev-list <SHA>..master --first-parent) | tail -1

或者为了更简洁和可重用,这里有一个可以弹出到.bashrc的函数:

function git-find-merge() {
  git rev-list $1..master --ancestry-path | grep -f <(git rev-list $1..master --first-parent) | tail -1
}

我使用下面的bash脚本,我放置在路径~/bin/git-find-merge。它基于Gauthier的答案和evilstreak的答案,并在处理极端情况时做了一些调整。当输入未排序时,Comm抛出。Grep -f工作得很完美。

角情况下:

如果commit是分支的第一个父路径上的合并提交,则返回commit。 如果commit在分支的第一个父路径上是非合并提交,则返回分支。要么是ff merge,要么是只在分支上提交没有办法确定正确的提交。 如果commit和branch相同,则返回commit。

~ / bin / git-find-merge脚本:

#!/bin/bash

commit=$1
if [ -z $commit ]; then
    echo 1>&2 "fatal: commit is required"
    exit 1
fi
commit=$(git rev-parse $commit)
branch=${2-@}

# if branch points to commit (both are same), then return commit
if [ $commit == $(git rev-parse $branch) ]; then
    git log -1 $commit
    exit
fi

# if commit is a merge commit on first-parent path of branch,
# then return commit
# if commit is a NON-merge commit on first-parent path of branch,
# then return branch as it's either a ff merge or commit is only on branch
# and there is not a good way to figure out the right commit
if [[ $(git log --first-parent --pretty='%P' $commit..$branch | \
    cut -d' ' -f1 | \
    grep $commit | wc -l) -eq 1 ]]; then
    if [ $(git show -s --format="%P" $commit | wc -w) -gt 1 ]; then
        # if commit is a merge commit
        git log -1 $commit
    else
        # if commit is a NON-merge commit
        echo 1>&2 ""
        echo 1>&2 "error: returning the branch commit (ff merge or commit only on branch)"
        echo 1>&2 ""
        git log -1 $branch
    fi
    exit
fi

# 1st common commit from bottom of first-parent and ancestry-path
merge=$(grep -f \
    <(git rev-list --first-parent  $commit..$branch) \
    <(git rev-list --ancestry-path $commit..$branch) \
        | tail -1)
if [ ! -z $merge ]; then
    git log -1 $merge
    exit
fi

# merge commit not found
echo 1>&2 "fatal: no merge commit found"
exit 1

这让我可以这样做:

(master)
$ git find-merge <commit>    # to find when commit merged to current branch
$ git find-merge <branch>    # to find when branch merged to current branch
$ git find-merge <commit> pu # to find when commit merged to pu branch

这个脚本也可以在我的github。

你可以尝试这样做。这个想法是遍历所有的合并提交,看看是否可以从其中一个提交“c”到:

$ git log --merges --format='%h' master | while read mergecommit; do
  if git log --format='%h' $mergecommit|grep -q $c; then
    echo $mergecommit;
    break
  fi
done

Git-get-merge将定位并显示你正在寻找的合并提交:

pip install git-get-merge
git get-merge <SHA-1>

该命令跟随给定提交的子分支,直到发现合并到另一个分支(假设是主分支)。