656

Mercurial から来て、ブランチを使用して機能を整理しています。当然、自分の歴史にもこのワークフローを見たいと思っています。

git を使用して新しいプロジェクトを開始し、最初の機能を完成させました。機能をマージするとき、git が早送りを使用していることに気付きました。つまり、可能であれば変更をマスター ブランチに直接適用し、私のブランチは忘れてしまいます。

将来を考えると、このプロジェクトに取り組んでいるのは私だけです。git のデフォルトのアプローチ (早送りマージ) を使用すると、私の履歴は 1 つの巨大なマスター ブランチになります。最終的には巨大な master ブランチしかないので、機能ごとに個別のブランチを使用したことを誰も知りません。それは専門外に見えませんか?

この理由から、私は早送りマージを望んでおらず、それがデフォルトである理由がわかりません。それについて何がそんなに良いのですか?

4

2 に答える 2

732

早送りマージは存続期間の短いブランチには理にかなっていますが、より複雑な履歴では、非早送りマージは履歴を理解しやすくし、コミットのグループを元に戻しやすくする場合があります。

警告: 非早送りにも潜在的な副作用があります。https://sandofsky.com/blog/git-workflow.htmlを確認し、バイセクトまたは非難を破る「チェックポイント コミット」による「no-ff」を回避し、それが のデフォルトのアプローチであるべきかどうかを慎重に検討してくださいmaster

代替テキスト
( nvie.comより、Vincent Driessenが「成功した 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フラグにより​​、マージが早送りで実行できる場合でも、マージは常に新しいコミット オブジェクトを作成します。これにより、機能ブランチの歴史的な存在に関する情報が失われるのを回避し、機能を一緒に追加したすべてのコミットをグループ化します。

Jakub Narębski構成について言及しています。merge.ff

デフォルトでは、現在のコミットの子孫であるコミットをマージするときに、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はコメントに追加します:

[短命の] ブランチの早送りにはある程度の意味がありますが、それをデフォルトのアクションにすることは、git があなたを想定していることを意味します... [短命の] ブランチがあることがよくあります。適正?

ジェフロミは次のように答えます。

ブランチの寿命はユーザーによって大きく異なると思います。ただし、経験豊富なユーザーの間では、存続期間の短いブランチの方がはるかに多い傾向があるでしょう。

私にとって、存続期間の短いブランチとは、特定の操作(リベース、可能性が高い、または迅速なパッチ適用とテスト) を容易にするために作成し、完了したらすぐに削除するブランチです。
つまり、分岐元のトピック ブランチに吸収される可能性が高く、トピック ブランチは 1 つのブランチとしてマージされます。特定の機能を実装する一連のコミットを作成するために、私が内部で行ったことを誰も知る必要はありません。

より一般的には、次のように付け加えます。

それは本当にあなたの開発ワークフローに依存します:

  • 線形の場合、1 つの分岐が意味を持ちます。
  • 機能を分離して長期間にわたって作業し、それらを繰り返しマージする必要がある場合は、いくつかの分岐が理にかなっています。

いつ分岐すべきか?」を参照してください。

実際、Mercurial ブランチ モデルを考えると、そのコアはリポジトリごとに1 つのブランチです (匿名のヘッド、ブックマーク、さらには名前付きブランチを作成できますが) 「Git と Mercurial - 比較と対照」 を
参照してください。

Mercurial は、デフォルトで匿名の軽量コードラインを使用します。これは、その用語では「ヘッド」と呼ばれます。
Git は軽量の名前付きブランチを使用し、リモート リポジトリ内のブランチの名前をリモート追跡ブランチの名前にマップするための単射マッピングを使用します。
Git はブランチに名前を付けるように「強制」します (ただし、名前のない単一のブランチは例外で、これは「切り離された HEAD」と呼ばれる状況です)、これはトピック ブランチ ワークフローなどのブランチの多いワークフローでうまく機能すると思います。つまり、単一のリポジトリ パラダイムでの複数のブランチ。

于 2010-05-17T15:31:36.253 に答える