簡単な解決策:マージ後に「work」ブランチを削除する
短い答え:マージを含め、好きなようにgitを使用できます(簡単なワークフローについては以下を参照)。ただ一時的な作業ブランチを削除するために、それぞれの「git merge work」と「git branch -d work」を必ず確認してください。
背景の説明:
マージ/ dcommitの問題は、ブランチを「git svn dcommit」すると、そのブランチのマージ履歴が「フラット化」されることです:gitは、このブランチに入ったすべてのマージ操作を忘れます:ファイルの内容のみが保持されますが、しかし、このコンテンツが(部分的に)特定の他のブランチからのものであるという事実は失われます。参照:git svn dcommitがローカルブランチのマージコミットの履歴を失うのはなぜですか?
(注:git-svnができることはそれほど多くありません。svnは、はるかに強力なgitマージを理解できません。そのため、svnリポジトリ内では、このマージ情報をどのようにも表すことができません。)
しかし、これが全体の問題です。「master」ブランチにマージされた後で「work」ブランチを削除すると、gitリポジトリは100%クリーンになり、svnリポジトリとまったく同じように見えます。
私のワークフロー:
もちろん、最初にリモートのsvnリポジトリーをローカルのgitリポジトリーに複製しました(これには時間がかかる場合があります)。
$> git svn clone <svn-repository-url> <local-directory>
すべての作業は「ローカルディレクトリ」内で行われます。サーバーから更新を取得する必要があるときはいつでも(「svn update」のように)、次のようにします。
$> git checkout master
$> git svn rebase
私はすべての開発作業を、次のように作成された別のブランチ「作業」で行います。
$> git checkout -b work
もちろん、好きなだけブランチを作成し、ブランチ間でマージしてリベースすることができます(以下で説明するように、ブランチが終わったら削除してください)。私の通常の作業では、非常に頻繁にコミットします。
$> git commit -am '-- finished a little piece of work'
次のステップ(git rebase -i)はオプションです--- svnでアーカイブする前に履歴をクリーンアップするだけです。他の人と共有したい安定したマイルストーンに到達したら、この「作品」の履歴を書き換えますコミットメッセージを分岐してクリーンアップします(他の開発者は、途中で行った小さな手順やミスをすべて見る必要はありません---結果だけです)。これのために、私はします
$> git log
そしてsvnリポジトリにある最後のコミットのsha-1ハッシュをコピーします(git-svn-idで示されます)。次に電話します
$> git rebase -i 74e4068360e34b2ccf0c5869703af458cde0cdcb
私の代わりに最後のsvn commitのsha-1ハッシュを貼り付けてください。詳細については、「git help rebase」のドキュメントをご覧ください。つまり、このコマンドは最初にコミットを表示するエディターを開きます-----以前のコミットでスカッシュしたいすべてのコミットの 'pick'を 'squash'に変更するだけです。もちろん、最初の行は「ピック」のままである必要があります。このようにして、多くの小さなコミットを1つ以上の意味のある単位にまとめることができます。保存してエディターを終了します。コミットログメッセージを書き換えるように求める別のエディタが表示されます。
簡単に言うと、「コードハッキング」を終えた後、他のプログラマにどのように提示したいか(または、履歴を参照して数週間で作業を確認したい方法)になるまで、「作業」ブランチをマッサージします。 。
変更をsvnリポジトリーにプッシュするために、次のようにします。
$> git checkout master
$> git svn rebase
これで、svnリポジトリーでその間に発生したすべての変更で更新された古い「master」ブランチに戻りました(新しい変更は「work」ブランチで非表示になっています)。
新しい「作業」の変更と衝突する可能性のある変更がある場合は、新しい作業をプッシュする前にローカルで解決する必要があります(以下の詳細を参照)。次に、変更をsvnにプッシュできます。
$> git checkout master
$> git merge work # (1) merge your 'work' into 'master'
$> git branch -d work # (2) remove the work branch immediately after merging
$> git svn dcommit # (3) push your changes to the svn repository
注1:コマンド 'git branch -d work'は非常に安全です。これは、不要になったブランチを削除することのみを許可します(現在のブランチに既にマージされているため)。作業を 'master'ブランチとマージする前にこのコマンドを誤って実行すると、エラーメッセージが表示されます。
注2:マージとdcommit の間に 'git branch -d work'を使用してブランチを必ず削除してください:dcommitの後にブランチを削除しようとすると、エラーメッセージが表示されます: 'git svn dcommit'を実行すると、gitはそれを忘れますあなたのブランチは 'master'とマージされました。安全性チェックを行わない「git branch -D work」で削除する必要があります。
ここで、すぐに新しい「work」ブランチを作成して、誤って「master」ブランチをハッキングしないようにします。
$> git checkout -b work
$> git branch # show my branches:
master
* work
「作業」とsvnの変更の統合:
「git svn rebase」が「work」ブランチの作業中に他の人がsvnリポジトリーを変更したことを明らかにしたとき、私は次のようにします。
$> git checkout master
$> git svn rebase # 'svn pull' changes
$> git checkout work # go to my work
$> git checkout -b integration # make a copy of the branch
$> git merge master # integrate my changes with theirs
$> ... check/fix/debug ...
$> ... rewrite history with rebase -i if needed
$> git checkout master # try again to push my changes
$> git svn rebase # hopefully no further changes to merge
$> git merge integration # (1) merge your work with theirs
$> git branch -d work # (2) remove branches that are merged
$> git branch -d integration # (2) remove branches that are merged
$> git svn dcommit # (3) push your changes to the svn repository
より強力なソリューションが存在
します:提示されたワークフローは単純化されています:「更新/ハック/ dcommit」の各ラウンド内でのみgitの機能を使用します---長期プロジェクトの履歴はsvnリポジトリと同じように線形のままです。これは、レガシーsvnプロジェクトの小さな最初のステップでgitマージの使用を開始したいだけの場合は問題ありません。
gitマージに慣れてきたら、他のワークフローを自由に探索してください:何をしているのかわかっている場合は、gitマージとsvnマージを混在させることができます(svnマージを支援するためだけにgit-svn(または類似の)を使用しますか?)