Git チームのワークフロー:マージかリベースか

Nicola Paolucci
Nicola Paolucci
リストに戻る

質問は簡単です。 gitフィーチャー ブランチを利用しているソフトウェアチームにとって、完了済みの作業を開発のメインラインに取り込む最も優れた方法は何でしょうか。これは、それぞれ強い主張を持つ両陣営が何度も繰り返している議論の一つですが、落ち着いた話し合いが時として難しくなる場合があるものです。 (激しい議論が交わされた他の例については、インターネット をご覧ください)。

Should you adopt a rebase policy where the repository history is kept flat and clean? Or a merge policy, which gives you traceability at the expense of readability and clarity (going so far as forbidding fast-forward merges)?

議論

このトピックは、vim と Emacs や Linux と BSD ほどまでには有名な論争の的とはなっていないものの、双方共に遠慮なく意見を述べ合っています。

My empirical pulse on all-things-git – scientific, I know! – is that the always merge approach has a slightly bigger mind share. But the always rebase field is also pretty vocal online. For examples see:

To be honest, the split in two camps – always rebase vs. always merge – can be confusing, because rebase as local cleanup is a different thing than rebase as team policy.

余談: コーディングのライフサイクルにおいては最高な、クリーンアップとしてのリベース

Rebase as team policy is a different thing than rebase as cleanup. Rebase as cleanup is a healthy part of the coding lifecycle of the git practitioner. Let me detail some example scenarios that show when rebasing is reasonable and effective (and when it's not):

  • You're developing locally. You have not shared your work with anyone else. At this point, you should prefer rebasing over merging to keep history tidy. If you've got your personal fork of the repository and that is not shared with other developers, you're safe to rebase even after you've pushed to your fork.
  • Your code is ready for review. You create a pull request, others are reviewing your work and are potentially fetching it into their fork for local review. At this point you should not rebase your work. You should create 'rework' commits and update your feature branch. This helps with traceability in the pull request, and prevents the accidental history breakage.
  • Review is done and ready to be integrated into the target branch. Congratulations! You're about to delete your feature branch. Given that other developers won't be fetch-merging in these changes from this point on, this is your chance to sanitize history. At this point you can rewrite history and fold the original commits and those pesky 'pr rework' and 'merge' commits into a small set of focussed commits. Creating an explicit merge for these commits is optional, but has value. It records when the feature graduated to master.

With this aside clear we can now talk about policies. I'll try to keep a balanced view on the argument, and will mention how the problem is dealt with inside Atlassian.

リベースチームポリシー: 定義、良い点と悪い点

It's obviously hard to generalize since every team is different, but we have to start from somewhere. Consider this policy as a possible example: When a feature branch's development is complete, rebase/squash all the work down to the minimum number of meaningful commits and avoid creating a merge commit – either making sure the changes fast-forward (or simply cherry-pick those commits into the target branch).

While the work is still in progress and a feature branch needs to be brought up to date with the upstream target branch, use rebase – as opposed to pull or merge – not to pollute the history with spurious merges.

良い点

  • コード履歴は、フラットかつ可読のままになります。クリーンかつ明確なコミットメッセージは、コードコメント、または課題トラッカーへのコメント等と同様にコードベースの文書の一部を構成しています。このため、単一のフィーチャーまたはバグ修正のために相殺してしまう、31の単一行のコミットで履歴を汚してしまわない事が重要です。このような状況においては、バグまたはフィーチャーが導入された時期とその理由を求めて履歴を遡って探し出す行為は、非常に難しくなります。
  • 単一のコミット操作が簡単(例、元に戻す)。

悪い点

  • 全ての開発履歴を備えた履歴ブランチを保持しておかない限り、フィーチャーを一握りのコミットにまで融合してしまうとコンテキストが隠れてしまいます。
  • Rebasing doesn't play well with pull requests, because you can't see what minor changes someone made if they rebased (incidentally, the consensus inside the Bitbucket Server development team is to never rebase during a pull request).
  • Rebasing can be dangerous! Rewriting history of shared branches is prone to team work breakage. This can be mitigated by doing the rebase/squash on a copy of the feature branch, but rebase carries the implication that competence and carefulness must be employed.
  • It's more work: Using rebase to keep your feature branch updated requires that you resolve similar conflicts again and again. Yes, you can reuse recorded resolutions (rerere) sometimes, but merges win here: Just solve the conflicts one time, and you're set.
  • Another side effect of rebasing with remote branches is that you need to force push at some point. The biggest problem we've seen at Atlassian is that people force push – which is fine – but haven't set git push.default. This results in updates to all branches having the same name, both locally and remotely, and that is dreadful to deal with.

NOTE: When history is rewritten in a shared branch touched by multiple developers breakage happens.

マージチームポリシー: 定義、良い点と悪い点

Always Merge-based policies instead flow like this: When a feature branch is complete merge it to your target branch (master or develop or next).

Make sure the merge is explicit with --no-ff, which forces git to record a merge commit in all cases, even if the changes could be replayed automatically on top of the target branch.

良い点

  • トレーサビリティ: フィーチャーブランチの歴史に関する情報を保持して、フィーチャーの全てのコミット部分を集合化します。

悪い点

  • History can become intensely polluted by lots of merge commits, and visual charts of your repository can have rainbow branch lines that don't add too much information, if not outright obfuscate what's happening. (Now to be fair, confusion is easily solved by knowing how to navigate your history; The trick here is to use, for example, git log --first-parent to make sense of what happened.)
Merge trees
  • Debugging using git bisect can become much harder due to the merge commits.

決断しなければなりません。あなたにとって最も重要なものは何でしょうか?

どれが一番良いのでしょうか?専門家のお勧めはどれでしょうか?

If you and your team are not familiar with, or don't understand the intricacies of rebase, then you probably shouldn't use it. In this context, always merge is the safest option.

If you and your team are familiar with both options, then the main decision revolves around this: Do you value more a clean, linear history? Or the traceability of your branches? In the first case go for a rebase policy, in the later go for a merge one.

また、リベースポリシーには少数の禁忌が存在するため、より多くの手間が要求されますのでご注意下さい。

アトラシアンのケース

The policy inside Atlassian's Bitbucket Server team is always to merge feature branches, and require that branches are merged through a pull request for quality and code review. But the team is not too strict around fast-forward.

結論と謝辞

This article is the result of the confluence of insightful exchanges (pun intended!) with the Bitbucket Server team on the topic.

This piece hopefully dispels the doubts on this, and allows you to adopt an approach that works for your team. Follow me @durdn, and the fantastic @AtlDevtools team for more git awesomeness.

Git を学習する準備はできていますか?

この対話式チュートリアルを利用しましょう。

今すぐ始める