web-dev-qa-db-ja.com

git rebaseとgit Push:非早送り、なぜ使用するのですか?

他の貢献者が利用できるはずのブランチがあり、マスターと常に最新の状態を保つ必要があります。

残念ながら、「git rebase」を実行してからプッシュしようとするたびに、「non-fast forward」メッセージとプッシュの中止が発生します。ここにプッシュする唯一の方法は、-forceを使用することです。私のブランチが公開され、他のブランチが作業している場合、リベースの代わりに「git merge」を使用する必要があるということですか?

68
snitko

gitの動作に関するいくつかの注意事項(非技術的):

リベースすると、gitは問題のコミットを取得し、クリーンな履歴の上にそれらを「推奨」します。これは、履歴が表示されないようにするためです。

Description: tree -> mywork -> merge -> mywork -> merge -> mywork -> merge
Commit SHA1: aaaa -> bbbb   -> cccc  -> dddd   -> eeee  -> ffff   -> gggg

リベース後、これは次のようになります(または同様)。

Description: tree -> rebase
Commit SHA1: aaaa -> hhhh

問題は、そこにプッシュしようとしている新しいコミットが、プッシュ先のブランチの先端にあるコミットの子孫ではないであるということです。

これで、同じ情報がコミットにあることがわかりますが、gitはそれらのコミットを上書きするだけでなく責任を負っています(上記の例ではbbbb-gggg)。


共有レポモデル

共有リポジトリを使用している場合、このようなことは非常に混乱する可能性があります。理由を説明させてください。別の開発者がブランチをプルダウンし、ブランチにコミットaaaa-> ggggがあるとします。その後、コミットを行いますiiii

その間、Pushをリベースして強制し、ツリーは次のようになりました。

Description: tree -> rebase
Commit SHA1: aaaa -> hhhh

他の開発者がプッシュしようとすると、「非早送り」メッセージが表示されます。彼がマージすると、両方の履歴が一緒に再リンクされ、最終的にmessになります。

このようなもの(乱雑):

Description: tree -> rebase -> mywork -> merge -> mywork -> merge -> mywork -> merge -> devwork -> merge 
Commit SHA1: aaaa -> hhhh   -> bbbb   -> cccc  -> dddd   -> eeee  -> ffff   -> gggg -> iiii    -> jjjj

言い換えれば、他の人が引っ張ったり押したりする場合は、git merge、またはAVOID PUSHINGをリベースの後(そして作業をリベースするだけ)続けることをお勧めします。


公開されているリポジトリモデル

おそらく、人々があなたのレポジトリからプルできるようにしたいだけの、別の(より派手な)モデルを使用しているのでしょう。この場合、git Push --forceはそれほど悪くありません。パッチを提供する前に、変更をリベースしてtheir changesを変更できます。それはあなたのレポがすべて台無しになるのを防ぎます。

ただし、より良い方法があるかもしれません。 git Push --mirror

http://www.kernel.org/pub/software/scm/git/docs/git-Push.htmlから

各参照にPushという名前を付ける代わりに、$ GIT_DIR/refs /(refs/heads /、refs/remotes /、およびrefs/tags /を含むがこれらに限定されない)の下のすべての参照をリモートリポジトリにミラーリングすることを指定します。新しく作成されたローカル参照はリモートエンドにプッシュされ、ローカルで更新された参照はリモートエンドで強制的に更新され、削除された参照はリモートエンドから削除されます。これは、構成オプションremote..mirrorが設定されている場合のデフォルトです。


gitの優れた点の1つは、非常に柔軟性があり、さまざまな種類のワークフローを使用できることです。しかし、本当の強みは分散モデルであるという事実にあるので、そのように使用することで最大限のROIを得ることができると信じています。

100
gahooa

いいえ、リベースは公開リポジトリで完全に合法であり、履歴を流に保つために望ましい場合さえあります。リベースを使用して、リモートで公開されたコミットの履歴を書き換えてはならないことに注意してください。つまり、リベースは、発行したことがない独自のローカルコミットにのみ適用できます。リベースを使用して、フェッチ時にコミットをコミットの上に配置し、おそらくそこで調整します。このようなメッセージを受け取る可能性があるもう1つの理由は、プッシュするブランチが更新されたため、フェッチしたものの上にコミットをフェッチしてリベースする必要があることです。

2
Val