私はもう1人の開発者とプロジェクトで数か月Gitを使用しています。私はSVNで数年の経験があるので、私は関係に多くの荷物を持っていると思います。
Gitはブランチやマージに最適であると聞いたことがありますが、今のところ見られません。もちろん、分岐は非常に単純ですが、私がマージしようとすると、すべてが地獄に行きます。今はSVNに慣れていますが、サブバージョン管理システムを別のシステムと交換したようです。
私のパートナーは、私の問題は意気揚々とマージしたいという私の欲求から生じていると私に言います、そして私は多くの状況でマージの代わりにリベースを使用すべきであると言います。たとえば、以下は彼が定めたワークフローです。
clone the remote repository
git checkout -b my_new_feature
..work and commit some stuff
git rebase master
..work and commit some stuff
git rebase master
..finish the feature
git checkout master
git merge my_new_feature
基本的に、機能ブランチを作成し、常にマスターからブランチにリベースし、ブランチからマスターにマージします。ブランチは常にローカルに留まることに注意してください。
これが私が始めたワークフローです
clone remote repository
create my_new_feature branch on remote repository
git checkout -b --track my_new_feature origin/my_new_feature
..work, commit, push to origin/my_new_feature
git merge master (to get some changes that my partner added)
..work, commit, push to origin/my_new_feature
git merge master
..finish my_new_feature, push to origin/my_new_feature
git checkout master
git merge my_new_feature
delete remote branch
delete local branch
2つの本質的な違いがあります(私は思う):リベースの代わりに常にマージを使用し、機能ブランチ(および機能ブランチのコミット)をリモートリポジトリにプッシュします。
リモートブランチについての私の推論は、自分が作業しているときに自分の作業をバックアップしたいというものです。リポジトリは自動的にバックアップされ、何か問題が発生した場合に復元できます。私のラップトップは完全ではありません。したがって、他の場所にミラーリングされていないコードをラップトップに置くのは嫌です。
リベースではなくマージの私の推論は、マージは標準のようであり、リベースは高度な機能のように思われるということです。私の直感は、私がやろうとしていることは高度なセットアップではないので、リベースは不要であるべきだということです。私はGitに関する新しいPragmatic Programmingの本を熟読しましたが、マージについて幅広くカバーしており、リベースについてはほとんど触れていません。
とにかく、私は最近のブランチでワークフローをフォローしていて、それをマスターにマージしようとすると、すべて地獄に行きました。重要ではないはずのこととの衝突がたくさんありました。紛争は私には意味がありませんでした。すべてを整理するのに1日かかり、ローカルマスターはすべての競合を解決したため、リモートマスターに強制的にプッシュすることになりましたが、リモートマスターはまだ満足していませんでした。
このようなものの「正しい」ワークフローは何ですか?Gitはブランチとマージを非常に簡単にするはずであり、私はそれを見ていません。
2011年4月15日更新
これは非常に人気のある質問のようです。最初に質問してから2年間の経験で更新したいと思いました。
少なくとも私たちの場合、元のワークフローは正しいことがわかります。言い換えると、これが私たちが行うことであり、機能します。
clone the remote repository
git checkout -b my_new_feature
..work and commit some stuff
git rebase master
..work and commit some stuff
git rebase master
..finish the feature, commit
git rebase master
git checkout master
git merge my_new_feature
実際、生のマージではなくスカッシュマージを行う傾向があるため、ワークフローは少し異なります。(注:これは議論の余地があります。以下を参照してください。)これにより、機能ブランチ全体をマスターでの単一のコミットに変えることができます。次に、機能ブランチを削除します。これにより、ブランチ上で少し厄介な場合でも、マスター上のコミットを論理的に構造化できます。それで、これが私たちがすることです:
clone the remote repository
git checkout -b my_new_feature
..work and commit some stuff
git rebase master
..work and commit some stuff
git rebase master
..finish the feature, commit
git rebase master
git checkout master
git merge --squash my_new_feature
git commit -m "added my_new_feature"
git branch -D my_new_feature
スカッシュマージの論争 -いくつかのコメント投稿者が指摘したように、スカッシュマージは機能ブランチのすべての履歴を破棄します。名前が示すように、すべてのコミットを1つにまとめます。小さな機能の場合、これを単一のパッケージに凝縮するので、これは理にかなっています。より大きな機能の場合、特に個々のコミットがすでにアトミックである場合、それはおそらく良いアイデアではありません。それは本当に個人的な好みに帰着します。
GithubとBitbucket(その他?)プルリクエスト -マージ/リベースがプルリクエストとどのように関係しているのか疑問に思っている場合は、マスターにマージする準備ができるまで、上記のすべての手順を実行することをお勧めします。手動でgitとマージする代わりに、PRを受け入れるだけです。これはスカッシュマージを行わないことに注意してください(少なくともデフォルトでは)、非スカッシュ、非早送りは、プルリクエストコミュニティで受け入れられているマージ規則です(私の知る限り)。具体的には、次のように機能します。
clone the remote repository
git checkout -b my_new_feature
..work and commit some stuff
git rebase master
..work and commit some stuff
git rebase master
..finish the feature, commit
git rebase master
git push # May need to force push
...submit PR, wait for a review, make any changes requested for the PR
git rebase master
git push # Will probably need to force push (-f), due to previous rebases from master
...accept the PR, most likely also deleting the feature branch in the process
git checkout master
git branch -d my_new_feature
git remote prune origin
私はGitが大好きになり、SVNに戻りたくありません。苦労している場合は、それに固執するだけで、最終的にトンネルの終わりに光が見えます。
rebase
理解に大いに役立ちました