如何为 git rebase 选择合并策略?

git-rebase手册页中提到的 -X<option>可以传递给 git-merge。确切的时间/方式?

我想通过使用 递归的策略和 他们的选项应用补丁来重新定位(应用任何粘贴,而不是跳过整个相互冲突的提交)。我不想合并,我想让历史线性化。

我试过了:

git rebase -Xtheirs

还有

git rebase -s 'recursive -Xtheirs'

但是 git 在两种情况下都拒绝 -X


git rebase -Xtheirs在最近的版本中可以工作,但是需要手动解决树冲突。在解决这些冲突之后,需要运行 git rebase -Xtheirs --continue(重复 -X)。

111454 次浏览

这是针对带有自己选项集的合并策略的

git rebase <branch> -s recursive -X theirs

虽然 这个贴片提到(2010年2月) :

页面上说 git-rebase支持合并策略,但是重定基 命令不知道 -X,并且给出了它的用法。

所以,如果它仍然不工作,它正在讨论的权利!
(在最近的 git 中支持)


来自 提交 db2b3b820e2b28da268cc88adff076b396392dfe的更新(2013年7月,git 1.8.4 +) ,

不要忽略交互式 rebase 中的合并选项

合并策略及其选项可以在 git rebase中指定,但在 -- interactive中,它们被完全忽略。

签名: Arnaud Fontaine

这意味着 -X和策略现在可以使用交互式 rebase 和普通 rebase。

您可以在 Gitv1.7.3或更高版本中使用它。

git rebase --strategy-option theirs ${branch} # Long option
git rebase -X theirs ${branch} # Short option

(这是 git rebase --strategy recursive --strategy-option theirs ${branch}的缩写,由 文件所述)

来自 Git v1.7.3发行说明:

git rebase --strategy <s>学习了 --strategy-option/-X选项来传递所选择的合并策略能够理解的额外选项。

注意: “我们的”和“他们的”的意思是他们在直线合并时的反义词。换句话说,“ their”倾向于在 目前分支上提交。

正如 我疯了所说,这个特性只适用于 git1.7.3以后的版本。因此,对于那些仍在使用1.7.1的可怜人(比如我) ,我提出了一个我自己做的解决方案:

Git-rebase-their

这是一个非常精心打磨(因此很长)的脚本,意味着生产使用: UI 选项,处理多个文件,检查文件是否实际上有冲突标记,等等,但“核心”可以总结为两行:

cp file file.bak
awk '/^<+ HEAD$/,/^=+$/{next} /^>+ /{next} 1' file.bak > file

以下是剧本全文:

#!/bin/bash
#
# git-rebase-theirs - Resolve rebase conflicts by favoring 'theirs' version
#
#    Copyright (C) 2012 Rodrigo Silva (MestreLion) <linux@rodrigosilva.com>
#
#    This program is free software: you can redistribute it and/or modify
#    it under the terms of the GNU General Public License as published by
#    the Free Software Foundation, either version 3 of the License, or
#    (at your option) any later version.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU General Public License for more details.
#
#    You should have received a copy of the GNU General Public License
#    along with this program. If not see <http://www.gnu.org/licenses/gpl.html>


#Defaults:
verbose=0
backup=1
inplace=0
ext=".bak"


message() { printf "%s\n" "$1" >&2 ; }
skip()    { message "skipping ${2:-$file}${1:+: $1}"; continue ; }
argerr()  { printf "%s: %s\n" "$myname" "${1:-error}" >&2 ; usage 1 ; }
invalid() { argerr "invalid option: $1" ; }
missing() { argerr "missing${1:+ $1} operand." ; }


usage() {
cat <<- USAGE
Usage: $myname [options] [--] FILE...
USAGE
if [[ "$1" ]] ; then
cat >&2 <<- USAGE
Try '$myname --help' for more information.
USAGE
exit 1
fi
cat <<-USAGE


Resolve git rebase conflicts in FILE(s) by favoring 'theirs' version


When using git rebase, conflicts are usually wanted to be resolved
by favoring the <working branch> version (the branch being rebased,
'theirs' side in a rebase), instead of the <upstream> version (the
base branch, 'ours' side)


But git rebase --strategy -X theirs is only available from git 1.7.3
For older versions, $myname is the solution.


It works by discarding all lines between '<<<<<<< HEAD' and '========'
inclusive, and also the the '>>>>>> commit' marker.


By default it outputs to stdout, but files can be edited in-place
using --in-place, which, unlike sed, creates a backup by default.


Options:
-h|--help            show this page.
-v|--verbose         print more details in stderr.


--in-place[=SUFFIX]  edit files in place, creating a backup with
SUFFIX extension. Default if blank is ""$ext"


--no-backup         disables backup


Copyright (C) 2012 Rodrigo Silva (MestreLion) <linux@rodrigosilva.com>
License: GPLv3 or later. See <http://www.gnu.org/licenses/gpl.html>
USAGE
exit 0
}
myname="${0##*/}"


# Option handling
files=()
while (( $# )); do
case "$1" in
-h|--help     ) usage            ;;
-v|--verbose  ) verbose=1        ;;
--no-backup   ) backup=0         ;;
--in-place    ) inplace=1        ;;
--in-place=*  ) inplace=1
suffix="${1#*=}" ;;
-*            ) invalid "$1"     ;;
--            ) shift ; break    ;;
*             ) files+=( "$1" )  ;;
esac
shift
done
files+=( "$@" )


(( "${#files[@]}" )) || missing "FILE"


ext=${suffix:-$ext}


for file in "${files[@]}"; do


[[ -f "$file" ]] || skip "not a valid file"


if ((inplace)); then
outfile=$(tempfile) || skip "could not create temporary file"
trap 'rm -f -- "$outfile"' EXIT
cp "$file" "$outfile" || skip
exec 3>"$outfile"
else
exec 3>&1
fi


# Do the magic :)
awk '/^<+ HEAD$/,/^=+$/{next} /^>+ /{next} 1' "$file" >&3


exec 3>&-


((inplace)) || continue


diff "$file" "$outfile" >/dev/null && skip "no conflict markers found"


((backup)) && { cp "$file" "$file$ext" || skip "could not backup" ; }


cp "$outfile" "$file" || skip "could not edit in-place"


((verbose)) && message "resolved ${file}"
done