确定合并是否将通过快进解决

时间:2016-06-06 02:47:55

标签: git merge fast-forward

我想知道在运行merge命令之前是否通过“fast-forward”解析特定合并。

我知道我可以通过“快进”(使用--no-ff选项)专门请求合并无法解决。或者我可以尝试仅通过快进来解决合并(使用--ff选项)。

但有时我想知道在运行之前是否会通过快进解决特定合并。我意识到理论上我可以通过挖掘历史树来解决这个问题。而且我也意识到我可以运行合并,看看会发生什么,但是如果我决定我更倾向于以其他方式解决合并,这会成为问题,因为我必须撤消合并(通过重新分配分支标签)在ref-log中)并再次进行。

注意:--dry-run问题(Is there a git-merge --dry-run option?)更多的是关于查看合并中可能存在的合并冲突,而不是关于可能通过快进解决的合并。

4 个答案:

答案 0 :(得分:5)

总结:git merge-base --is-ancestor测试一个提交是否是另一个提交的祖先(提交被认为是他们自己的祖先,这是一种特别奇怪的乱伦形式,也许是:-))。由于当前分支(git merge)指向作为另一个提交的祖先的提交时,分支标签只能由HEAD快进,我们可以使用它来确定是否{{1可以进行快进操作。

看起来你想把这个贴出来作为答案,所以我把它转换成了一个工作的git别名,你可以把它放在你的全局git配置中。别名有点长且复杂,最好将它剪切并粘贴到你的git config别名部分:

git merge

这是与shell脚本相同的东西,以更易读的方式和一些评论:

canff = "!f() { if [ $# -gt 0 ]; then b=\"$1\"; git rev-parse -q --verify \"$b^{commit}\" >/dev/null || { printf \"%s: not a valid commit specifier\n\" \"$b\"; return 1; } else b=$(git rev-parse --symbolic-full-name --abbrev-ref @{u}) || return $?; fi; if git merge-base --is-ancestor HEAD \"$b\"; then echo \"merge with $b can fast-forward\"; else echo \"merge with $b cannot fast-forward\"; fi; }; f"

shell脚本只需要一个主要部分来驱动它,即在别名之后调用#! /bin/sh # # canff - test whether it is possible to fast-forward to # a given commit (which may be a branch name). If given # no arguments, find the upstream of the current (HEAD) branch. # First, define a small function to print the upstream name # of the current branch. If no upstream is set, this prints a # message to stderr and returns with failure (nonzero). upstream_name() { git rev-parse --symbolic-full-name --abbrev-ref @{u} } # Now define a function to detect fast-forward-ability. canff() { local b # branch name or commit ID if [ $# -gt 0 ]; then # at least 1 argument given b="$1" # make sure it is or can be converted to a commit ID. git rev-parse -q --verify "$b^{commit}" >/dev/null || { printf "%s: not a valid commit specifier\n" "$b" return 1 } else # no arguments: find upstream, or bail out b=$(upstream_name) || return $? fi # now test whether git merge --ff-only could succeed on $b if git merge-base --is-ancestor HEAD "$b"; then echo "merge with $b can fast-forward" else echo "merge with $b cannot fast-forward" fi } 。别名本身只是将fcanff中的所有内容划分为一行。然后Git的配置文件规则要求用双引号引用整个别名,这反过来要求所有内部双引号都转换为反斜杠双引号序列。

(我还拿出了upstream_name语句,因为作为别名,每次都会激活一个新的shell实例,因此变量名称的卫生变得不重要。)

(实际上可以将别名写成多行。只需在每个换行符前加上反斜杠。但是,这个别名非常复杂,看起来也很丑陋,所以我最后只留下一个大行。)< / p>

答案 1 :(得分:1)

您可以测试git merge-base <branch1> <branch2>是否等于git rev-parse <branch1>。如果相等,则在运行git merge <branch1> <branch2>时ff合并或已经是最新的。如果没有,非ff合并。

function isff(){
a=$(git merge-base $1 $2)
b=$(git rev-parse $1)
c=$(git rev-parse $2)
if [[ "$b"  == "$c" ]] || [[ "$a" == "$c" ]];then
    echo merge dry run: already up-to-date
    return
fi
if [ "$a" == "$b" ];then
    echo merge dry run: a fast forward merge
else
    echo merge dry run: a non fast forward merge
fi
}

isff master topic

答案 2 :(得分:0)

这里有一个类似但不完全相同的问题:Is there a git-merge --dry-run option?

第一个答案看起来可能就是您正在寻找的内容。

具体来说,merge标有--no-commit标记并在您看到足够的时候使用--abort,并希望返回并进行实际合并。

答案 3 :(得分:0)

看看@ Ashwin-nair引用的问题,我发现我认为是一个答案。

有关

git checkout MY_BRANCH 
git merge OTHER_BRANCH 

如果输出

git branch --contains MY_BRANCH

包含OTHER_BRANCH,然后可以通过快进解决与OTHER_BRANCH的合并。