web-dev-qa-db-ja.com

公開されているブランチのリベース

git-rebaseの使用方法を理解できず、次の例を検討します。

~/tmp/repoでリポジトリを開始しましょう:

$ git init

次に、ファイルを追加しますfoo

$ echo "hello world" > foo

これが追加され、コミットされます。

$ git add foo
$ git commit -m "Added foo"

次に、リモートリポジトリを起動しました。 ~/tmp/bare.git

$ git init --bare

repobare.gitにリンクするために実行しました

$ git remote add Origin ../bare.git/
$ git Push --set-upstream Origin master

次に、ブランチを作成してファイルを追加し、新しいブランチb1のアップストリームを設定します。

$ git checkout -b b1
$ echo "bar" > foo2
$ git add foo2
$ git commit -m "add foo2 in b1"
$ git Push --set-upstream Origin b1

今度はmasterに戻り、そこで何かを変更します。

$ echo "change foo" > foo
$ git commit -a -m "changed foo in master"
$ git Push

この時点でmasterのファイルfooにはchanged fooが含まれていますが、b1ではhello world。最後に、b1masterでの進行状況と同期させます。

$ git checkout b1
$ git fetch Origin
$ git rebase Origin/master

この時点でgit stは次を返します:

# On branch b1
# Your branch and 'Origin/b1' have diverged,
# and have 2 and 1 different commit each, respectively.
#   (use "git pull" to merge the remote branch into yours)
#
nothing to commit, working directory clean

この時点で、ブランチb1fooの内容もchange fooです。では、この警告はどういう意味ですか?私はgit Pushをやるべきだと思っていました、gitはgit pullを行うことを提案しています... この答え によると、これは多かれ少なかれそれであり、彼のコメントで@FrerichRaabeが明示的にプルする必要はないと言って。何が起きてる?危険は何ですか、どのように進めるべきですか?履歴をどのように一貫させる必要がありますか?上記のケースと次の引用の間の相互作用は何ですか?

公開リポジトリにプッシュしたコミットをリベースしないでください。

pro git book から取得。

私はそれが何らかの形で関連していると思います。そうでない場合、私はその理由を知りたいと思います。上記のシナリオと私が説明した手順の関係は何ですか この投稿で

8
Dror

パブリックリポジトリにプッシュしたコミットをリベースしたくない理由は、git-rebaseコマンドは履歴を変更します。

さて、それはどういう意味ですか、なぜそれが悪いのですか?まず、Gitブックの このセクション を読むことをお勧めします。そのことから、コミットがツリーオブジェクトへのポインター(ファイルのスナップショット)と親コミットへのポインターで構成されていることがわかります。新しいコミットの上にコミットをリベースして「変更履歴」を作成すると、既に行ったコミットの親ポインターが変更され、コミットのIDが変更されます。

これが悪い理由は、コミットを公に共有し、他の人がそれらのコミットに基づいて追加の作業を開始すると、それらのコミットに変更を加えると、ツリーが同期しなくなるためです。

いくつかのgit-logコマンドを使用して、例を実行します。私はrebaseコマンドを実行する直前にこれらを実行しました:

$ git log --pretty=oneline Origin/master
9b077261d1619803213201d5c7cefb757eb66b67 Changed foo in master
911ce5b247e79682ec9f73ad9a15fd3167b7e76d Added foo

$ git log --pretty=oneline Origin/b1
63a57ef54e301314a9dab38de0cd9d88c59a5fba added foo2 in b1
911ce5b247e79682ec9f73ad9a15fd3167b7e76d Added foo

$ git log --pretty=oneline b1
63a57ef54e301314a9dab38de0cd9d88c59a5fba added foo2 in b1
911ce5b247e79682ec9f73ad9a15fd3167b7e76d Added foo

そして今、リベースを実行した後、Origin/masterおよびOrigin/b1は同じですが、b1 今です:

$ git log --pretty=oneline b1
6687c64c37db0ee21a4d87e45d6ccb0913b8686d added foo2 in b1
9b077261d1619803213201d5c7cefb757eb66b67 Changed foo in master
911ce5b247e79682ec9f73ad9a15fd3167b7e76d Added foo

「b1に追加されたfoo2」コミットには、前のログコマンドとは異なるIDがあることがわかります。この変更をパブリックリポジトリにコミットすると、2つのコミットで同じ作業が行われ、問題が発生します。

ここで、b1をmasterの上にリベースするのではなく、masterをb1にマージしただけで、ログは次のようになるとします。

$ git checkout b1
$ git merge Origin/master
$ git log --pretty=oneline b1
518eb2dc6b2da0ff43ddd6837332031cc00eaad1 Merge remote-tracking branch 'Origin/master' into b1
9b077261d1619803213201d5c7cefb757eb66b67 Changed foo in master
63a57ef54e301314a9dab38de0cd9d88c59a5fba added foo2 in b1
911ce5b247e79682ec9f73ad9a15fd3167b7e76d Added foo

以前の2つのコミットのマージを表す追加のコミットに気付くでしょう。この歴史を共有することができ、誰もが幸せになります。

git-log --graphはまた、何が起こっているかについていくつかの追加の光を当てるのに役立ちます。

7
heavyd

パーティーで遅くなりましたが、これが後世の答えです:

git rebaseはローカルで使用するためのものです。それは履歴を書き換えます。これは非常に素晴らしい「メインライン」を可能にしますが、マルチユーザー環境では危険です

次の場合:

  • リモートリポジトリを使用しているのはあなただけです。
  • また、1つのワークスペースでのみ使用している場合

次に、可能性がありますこれは、履歴を強制的に再書き込みすることで実現できます。リベースを実行してから:

git push -f Originリモートブランチ

これらの仮定のいずれかが満たされていない場合は、このアクションを後悔するために生きるかもしれません:-)

このブログ投稿で詳細を読む

2
Omri Spector