如何在自定义Git合并驱动程序中检索分支名称?

时间:2014-06-19 08:57:54

标签: git git-merge

我正在编写一个自定义合并驱动程序,需要知道它正在合并的分支的名称。我设法检索了与git symbolic-ref HEAD合并到(目标)的分支的名称,以及从GITHEAD_<SHA>环境变量合并到(源)的分支的名称。

# retrieve merged branch name from an env var GITHEAD_<sha>=<branchName> 
# we cannot use a sym ref of MERGE_HEAD, as it doesn't yet exist 
gitHead=$(env | grep GITHEAD) # e.g. GITHEAD_<sha>=release/1.43 
# cut out everything up to the last "=" sign 
source="${gitHead##*=}"

# retrieve base branch name from a sym ref of HEAD 
branch=$(git symbolic-ref HEAD) # e.g. refs/heads/master 
# cut out "refs/heads"
destination="${branch#refs/heads/}"

echo "Merging from $source into $destination"

这是正确的做法吗?特别是,从环境变量中检索 source 名称似乎很不稳定。请注意,此时MERGE_HEAD不存在,因此我不能使用与HEAD相同的方法。

2 个答案:

答案 0 :(得分:1)

是的,这与合并驱动程序中的距离非常接近。

合并策略通过查找每个GITHEAD_%s获取正确的名称,其中每个%s参数都从给定合并策略的参数中填充,每个“远程头”。有关详细信息,请参阅my answer to a related question。这在任何地方都没有记录,只是from the source。不幸的是,当您进入合并驱动程序时,this information is lost:没有%指令可以检索这些名称,即使可能存在。 (添加一些%指令应该很简单:只需增加字典的大小并添加适当的指令和strbuf对象。)

如果你正在处理一个正常的双头和一个基础的合并,那么只有一个GITHEAD_*变量而且它是另一个头,但如果你正在处理一个章鱼合并,那你就不走运了

答案 1 :(得分:0)

我已经处理了几周的任务,并且发现了一些脚本无法正确处理的极端情况。到处搜索并查看Git来源,我已经找到了这个脚本:

#!/bin/bash 
# ${1} is the base common file 
# ${2} is the file as modified by the base branch, and where the results must be 
# ${3} is the file as modified by the incoming branch / stash
# ${4} is the path of the file being merged

# does not support octopus merge.

branch=$(git symbolic-ref --short HEAD || git name-rev --name-only HEAD)
githeadNum=$(env | grep GITHEAD | wc -l) # pathces do not create any GITHEAD var


# get a GITHEAD with message 'Stashed changes'
# if we are applying a stash, it must exist.
# see https://github.com/git/git/blob/2d08f3deb9feb73dc8d21d75bfd367839fc1322c/git-stash.sh#L616
stash=$(env | grep -E 'GITHEAD_[0-9a-f]{40}\b*=\b*Stashed changes' | wc -l) # e.g. GITHEAD_<sha>=Stashed changes 

if [ "$stash" -eq "1" ]
then
    # we are in a stash 
else
    if [ "$githeadNum" -eq "0" ]
    then
        # we are in a patch
    else
        # normal merge

        # only one GITHEAD, merging
        gitHeadName=$(env | grep GITHEAD)
        source="${gitHeadName##*=}"
    fi
fi

exit 1 

我将目标分支恢复为

$(git symbolic-ref --short HEAD || git name-rev --name-only HEAD)

我发现第一部分失败了rebase,因此如果需要重新设置基准,第二部分应该可以工作。

对于源代码,我解析了GITHEAD env变量,但检查了补丁程序或隐藏应用程序,因为我想以不同的方式处理这些情况(补丁程序不会离开GITHEAD)

适用于藏匿处:

stash=$(env | grep -E 'GITHEAD_[0-9a-f]{40}\b*=\b*Stashed changes' | wc -l)

如果我们处于隐藏状态,$ stash将为1,否则为0

对于补丁,我计算GITHEAD的数量,该数量必须为零:

githeadNum=$(env | grep GITHEAD | wc -l)