この方法でブランチをマージしやすくなり、競合が少なくなります。
トランクを新しいブランチにコピーし、機能ブランチとマージします。完了したら、新しいブランチをトランクにマージします。この手法は、Mercurialとgitのリベースによく似ています。
以前は、トランクから機能branche/sへの変更をマージしていました。しかし、後で機能ブランチをトランクにマージして戻すと、トランクからのものの一部が再びトランクにマージされ、多くの競合が発生しました。再統合マージの選択がありますが、私にはうまくいかないようでした。
誰もが似たようなSubversionリベースを行いますか?私は最近これを始めたばかりで、副作用を見ていません。これにより、予期しない問題が発生しますか?
一般的に、リベースとは、機能ブランチを上流ブランチにマージする前に、上流ブランチの変更を機能ブランチに組み込む行為です。
Gitでは、ブランチが作成されてから行われた変更が最初に取り外されてバッファリングされ、アップストリームの変更が適用され、次にバッファされた変更が適用されるため、プロセスはさらに洗練されます。ここでの要点は、トランクを機能ブランチにマージすることであり、gitの用語ではリベースではありません。 gitアプローチには多くの利点がありますが、すべてのコミットをサーバーに保存する必要があるため(svnは配布されないため)、svnでは非常にきれいに実装できませんが、svnではcanを実行します。
'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
トランクを機能ブランチに単純にマージすることとの違いがわかりますか?この例では、上流の最新のトランクから開始し、機能からの変更をその上にマージします。
トランクでのコミットの一部は、別の機能ブランチをトランクにマージすることで発生する可能性があることを想像してください。そのため、直接トランクにコミットすることを主張していません。
SVNでリベースを実現する方法を教えてくれる巧妙なトリックがあればいいのにと思いますが、主にjdehaanが言及している手動でのチェリーピッキングを必要とする複雑さのために、SVNでトランクの変更を伴うブランチの手動更新を常に避けています。
私が代わりに行うことは、通常、ブランチからトランクへの変更をマージし、ブランチを削除してから、トランクからブランチを再作成するというプラクティスに従います。これにより、機能ブランチを更新/リベースできますが、そのブランチからの以前の変更がトランクの一部になるという不幸な副作用があります。このため、機能ブランチが安定して使用可能なポイントにある場合にのみこのプラクティスに従いますが、さらに大きな目的をさらに完了するために、その機能の作業を続けたいと考えています。
私が好むのは、トランクの変更をブランチにマージしてブランチをリフレッシュすると、その後のブランチからの再統合マージがプロセス中にリベースされたリビジョンをプルしないことです。 merge-infoプロパティに基づいてこれを行うことは可能であるはずですが、jdehaanが述べていることと私が恐れていることによると、これを行うにはチェリーピッキングが必要です。
適切なリベースの実装では、別のブランチからブランチが作成される階段の例を考慮することもできることに注意してください。
更新:Subversionドキュメントによると、 -reintegrateを使用するとoption Subversionは、ベースの変更をブランチに取り込むために行われた可能性のある更新マージを考慮して、ブランチで行われた作業を適切に再統合できる必要があります。もちろん、これは技術的にはリベースとは少し異なりますが、リベースと呼ばれるほど使用方法が似ていると思います。
私の会社では、次のアプローチを使用しています。
タスクNK- $ Xが1反復サイクルより長く続き、更新が必要な場合は、決してトランクを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'
このように、ブランチ/ NK- $ Xの変更ログを見ると、開発者によって実際に実行された変更のみが表示されます。
更新:上記のワークフローは自動化できるため、githubでプロジェクトを開始しました: svn rebase 。
使用する git svn
:
git svn clone -s <link to svn trunk/branches/tags parent>
git rebaseコマンドを使用してください
私は、svnのリベースのようなgitを実行するスクリプトを使用します。
#!/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
他のブランチのリビジョンを1つずつマージします。
私はこのアプローチを使用しています:
リベースでは、再度マージするときにリベースされたリビジョンを引き継がないように注意する必要があります。マージに関しては、チェリーピッキングを行います。機能ベースの変更セットではなく、何か新しいものを実装するリビジョンのみを選択します。その後、正常に動作するはずです。コメント:何かのために再統合ブランチを使用したことを思い出すことはできません。非常に単純なユースケースのみを対象としていると思います。
新しいアプローチでは、必要に応じてトランクから機能ブランチへのリベースをどのように処理するかは説明から明らかではありません。リベースを完全に禁止しますか? svnでの分岐は安価な操作であるため、これもオプションです。