我曾经将主干的任何更改合并到功能分支中。但是稍后当我将功能分支合并回主干时,一些来自主干的东西会再次合并回主干,这导致了很多冲突。有一种重新整合合并的选择,但对我似乎不起作用。 有人使用类似于svn的rebasing吗? 我最近刚开始尝试这样做,还没有看到任何副作用。 这会导致任何未预见的问题吗?将主干复制到一个新的分支,将其与功能分支合并。完成后,将新的分支合并回主干。这个技巧很像mercurial和git的rebasing。
我曾经将主干的任何更改合并到功能分支中。但是稍后当我将功能分支合并回主干时,一些来自主干的东西会再次合并回主干,这导致了很多冲突。有一种重新整合合并的选择,但对我似乎不起作用。 有人使用类似于svn的rebasing吗? 我最近刚开始尝试这样做,还没有看到任何副作用。 这会导致任何未预见的问题吗?将主干复制到一个新的分支,将其与功能分支合并。完成后,将新的分支合并回主干。这个技巧很像mercurial和git的rebasing。
一般而言,rebase(变基)是将上游更改合并到功能分支中,然后再将功能分支合并回上游分支的操作。
在git中,此过程更加复杂,因为首先需要将自分支创建以来所做出的更改取出并缓存,再应用上游更改,最后再应用缓存的更改。这里要注意的是,在git术语中,将主干分支合并到功能分支不是rebase,还有其他操作需要执行。Git的方法具有许多优点,但无法在svn中实现得非常干净,因为所有提交都必须存储在服务器上(svn不是分布式版本控制系统),但它在svn中也可以实现。
“svn rebase”(git的方式)可能看起来像这样:
svn cp trunk feature
svn cp trunk feature-rebase
svn co feature-rebase
cd feature-rebase
svn merge feature
svn commit
svn rm feature
svn mv feature-rebase feature
svn switch feature
然后最终在主干的工作副本上,svn merge --reintegrate feature
您看到与仅将主干合并到功能分支的差异了吗?您要从上游开始,以这个例子为例就是trunk,然后将功能分支的更改合并到其中。
想象一下,主干的某些提交可能来自将另一个功能分支合并到主干中,因此我绝不建议直接提交到主干。
更新:根据Subversion文档,当使用--reintegrate选项时,Subversion应该能够以一种注意任何可能的刷新合并的方式正确地重新整合在分支中完成的工作。当然,这从技术上讲与变基略有不同,但我认为在用法上足够相似,可以称之为变基。
如果任务NK-$X持续时间超过一个迭代周期,并且因此需要刷新,我们永远不会将主干合并到NK-$X中。我们有一个规则,只有你自己编写的内容才能提交到你的分支,这使得一切变得更加容易。相反,我们会执行以下操作:
cd NK-$X
svn log
//let L = the number of the last changeset to this branch changeset
//let F = the number of the first changeset to this branch
svn rm branches/NK-$X
svn cp trunk branches/NK-$X
svn up
svn merge -r F:L branches/NK-$X@L
svn ci -m 'refereshed'
使用 git svn
:
git svn clone -s <SVN主干/分支/标签父节点链接>
然后随意使用 git rebase
命令。
Original Answer 翻译成“最初的回答”。
我使用一个脚本,类似于 git 的 rebase 功能,但是用于 svn:
#!/bin/bash
set_safe()
{
set -eo pipefail
}
validate_number()
(
if (! [ "$1" -eq "$1" ] 2>/dev/null ) then
{
echo "$1 is not a number"
return 1
}
fi
)
get_line()
(
set_safe
#head -n "$1" | tail -n 1
sed -n "${1}p;$(($1+1))q"
)
split_trim()
(
set_safe
tr "$1" '\n' | sed -e 's/^\s*//;' -e 's/\s*$//'
)
run_svn()
(
set +x
#echo "svn $*" 1>&2
svn --non-interactive --password "$svn_password" "$@"
)
rebase()
(
set_safe
url="$1"
cur="$2"
end="$3"
validate_number "$cur"
if ([ -z "$end" ] || [ "$end" = "HEAD" ]) then
{
end="$(run_svn info "$url" | grep "Last Changed Rev" | cut -d' ' -f4)"
echo "end: $end"
}
else
{
validate_number "$end";
}
fi
while (true) do
{
log="$(run_svn log "$url" -l1 -r "$cur:HEAD")"
meta="$(echo -n "$log" | get_line 2 | split_trim '|')"
next="$(echo -n "$meta" | get_line 1 | tail -c +2)"
author="$(echo -n "$meta" | get_line 2)"
date="$(echo -n "$meta" | get_line 3 | awk '{print $1, $2, $3}')"
msg="$(echo -n "$log" | tail -n +4 | head -n -1)"
cur=$next
if ([ -z $cur ] || [ $cur -gt $end ]) then { break; } fi
echo "$msg" > .msg
echo "Merging revision $cur:"
echo "========"
cat .msg
echo "========"
run_svn merge "$url" -c $cur
run_svn commit -F .msg
rm -f .msg
run_svn update
echo "Success"
echo
cur=$(($cur + 1))
}
done
)
if ([ -z "$1" ]) then
{
echo "Usage:"
echo " svn-rebase.sh <url> <begin revision> [end revision]"
exit
}
fi
echo -n "svn password: "
read -s svn_password
echo
rebase "$1" "$2" "$3"
err=$?
if ([ $err -ne 0 ]) then { echo "rebase failed: $err"; } fi
exit $err
它逐一合并来自其他分支的修订。