私は Mercurial から移行したので、ブランチを使用して機能を整理しています。当然、このワークフローを自分の履歴でも確認したいと思っています。
私は git を使用して新しいプロジェクトを開始し、最初の機能を完成させました。機能をマージするときに、git が fast-forward を使用していることに気付きました。つまり、可能であれば変更をマスター ブランチに直接適用し、自分のブランチを忘れるのです。
将来について考えてみましょう。このプロジェクトに取り組んでいるのは私だけです。git のデフォルトのアプローチ (Fast Forward マージ) を使用すると、履歴は 1 つの巨大なマスター ブランチになります。最終的にその巨大なマスター ブランチしか残らないため、機能ごとに別のブランチを使用したことは誰にもわかりません。プロフェッショナルに見えませんか?
この理由から、私は早送りマージを望まないし、それがなぜデフォルトなのか理解できません。何がそんなに良いのでしょうか?
ベストアンサー1
早送りマージは短命なブランチには有効だが、より複雑な歴史非早送りマージにより、履歴が理解しやすくなり、コミットのグループを元に戻しやすくなります。
警告: 早送りをしない場合にも副作用が生じる可能性があります。git ワークフロー、bisect または Blame を中断する「チェックポイント コミット」を含む「no-ff」を避け、それが のデフォルトのアプローチであるべきかどうかを慎重に検討してくださいmaster
。
(からホームページ、ヴィンセント・ドリセン、 役職 "成功したGitブランチモデル)
完成した機能を開発に組み込む
完成した機能は、開発ブランチにマージされ、次のリリースに追加される可能性があります。
$ git checkout develop Switched to branch 'develop' $ git merge --no-ff myfeature Updating ea1b82a..05e9557 (Summary of changes) $ git branch -d myfeature Deleted branch myfeature (was 05e9557). $ git push origin develop
この
--no-ff
フラグにより、マージが fast-forward で実行できる場合でも、マージによって常に新しいコミット オブジェクトが作成されます。これにより、機能ブランチの履歴的な存在に関する情報が失われることが回避され、機能を追加したすべてのコミットがグループ化されます。
デフォルトでは、Git は現在のコミットの子孫であるコミットをマージするときに追加のマージコミットを作成しません。代わりに、現在のブランチの先端が早送りされます。
に設定するとfalse
、この変数は、そのような場合に Git に追加のマージコミットを作成するように指示します (--no-ff
コマンドラインから オプションを指定するのと同じです)。
' ' に設定するとonly
、そのような早送りマージのみが許可されます (--ff-only
コマンドラインから オプションを指定するのと同じです)。
早送りがデフォルトである理由は次のとおりです。
- 短命ブランチはGitで簡単に作成、使用できます。
- 短命なブランチは、そのブランチ内で自由に再編成できる多くのコミットを分離することが多い。
- これらのコミットは実際にはメイン ブランチの一部です。再編成されると、メイン ブランチが高速化されてそれらが含まれるようになります。
ただし、1 つのトピック/機能ブランチで反復的なワークフローが予想される場合 (つまり、マージしてからこの機能ブランチに戻ってさらにコミットを追加する場合)、機能ブランチのすべての中間コミットではなく、メイン ブランチにマージのみを含めると便利です。
この場合、設定はこの種の設定ファイル:
[branch "master"]
# This is the list of cmdline options that should be added to git-merge
# when I merge commits into the master branch.
# The option --no-commit instructs git not to commit the merge
# by default. This allows me to do some final adjustment to the commit log
# message before it gets commited. I often use this to add extra info to
# the merge message or rewrite my local branch names in the commit message
# to branch names that are more understandable to the casual reader of the git log.
# Option --no-ff instructs git to always record a merge commit, even if
# the branch being merged into can be fast-forwarded. This is often the
# case when you create a short-lived topic branch which tracks master, do
# some changes on the topic branch and then merge the changes into the
# master which remained unchanged while you were doing your work on the
# topic branch. In this case the master branch can be fast-forwarded (that
# is the tip of the master branch can be updated to point to the tip of
# the topic branch) and this is what git does by default. With --no-ff
# option set, git creates a real merge commit which records the fact that
# another branch was merged. I find this easier to understand and read in
# the log.
mergeoptions = --no-commit --no-ff
OP はコメントで次のように付け加えています:
[短命] ブランチの fast-forward には意味があると思いますが、これをデフォルトのアクションにすると、git は [短命] ブランチが頻繁にあると想定することになります。合理的ですか?
ジェフロミは答えます:
ブランチの有効期間はユーザーによって大きく異なると思います。ただし、経験豊富なユーザーの間では、有効期間の短いブランチがはるかに多くなる傾向があります。
私にとって、短命ブランチとは、特定の操作(おそらくリベース、または簡単なパッチ適用とテスト) を簡単にするために作成し、完了したらすぐに削除するブランチです。
つまり、そのブランチは、フォーク元のトピック ブランチに吸収され、トピック ブランチは 1 つのブランチとしてマージされる可能性が高いということです。特定の機能を実装する一連のコミットを作成するために私が内部で行ったことを、誰も知る必要はありません。
より一般的には、次のように付け加えます。
それは本当にあなたの開発ワークフロー:
- 線形の場合、1 つのブランチが意味を持ちます。
- 機能を分離して長期間作業し、繰り返しマージする必要がある場合は、複数のブランチが適切です。
見る "いつ分岐すべきでしょうか?「
実際、Mercurialのブランチモデルを考えると、その核心はリポジトリごとに1つのブランチ(作成することはできますが匿名のヘッド、ブックマーク、さらには名前付きブランチ)
見る「Git と Mercurial - 比較と対比」。
Mercurial はデフォルトで、匿名の軽量コードラインを使用します。これは、その用語では「ヘッド」と呼ばれます。Git
は軽量の名前付きブランチを使用し、リモート リポジトリのブランチ名をリモート追跡ブランチ名にマッピングする注入マッピングを使用します。Git
は、ブランチに名前を付けることを「強制」します (ただし、名前のない単一のブランチは例外で、これは「切り離されたヘッド") ですが、これはトピック ブランチ ワークフローなどのブランチを多用するワークフロー、つまり単一のリポジトリ パラダイムで複数のブランチを実行するワークフローでより適切に機能すると思います。