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
repo
をbare.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。最後に、b1
をmaster
での進行状況と同期させます。
$ 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
この時点で、ブランチb1
のfoo
の内容もchange fooです。では、この警告はどういう意味ですか?私はgit Push
をやるべきだと思っていました、gitはgit pull
を行うことを提案しています... この答え によると、これは多かれ少なかれそれであり、彼のコメントで@FrerichRaabeが明示的にプルする必要はないと言って。何が起きてる?危険は何ですか、どのように進めるべきですか?履歴をどのように一貫させる必要がありますか?上記のケースと次の引用の間の相互作用は何ですか?
公開リポジトリにプッシュしたコミットをリベースしないでください。
pro git book から取得。
私はそれが何らかの形で関連していると思います。そうでない場合、私はその理由を知りたいと思います。上記のシナリオと私が説明した手順の関係は何ですか この投稿で 。
パブリックリポジトリにプッシュしたコミットをリベースしたくない理由は、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
はまた、何が起こっているかについていくつかの追加の光を当てるのに役立ちます。
パーティーで遅くなりましたが、これが後世の答えです:
git rebase
はローカルで使用するためのものです。それは履歴を書き換えます。これは非常に素晴らしい「メインライン」を可能にしますが、マルチユーザー環境では危険です
次の場合:
次に、可能性がありますこれは、履歴を強制的に再書き込みすることで実現できます。リベースを実行してから:
git push -f Originリモートブランチ
これらの仮定のいずれかが満たされていない場合は、このアクションを後悔するために生きるかもしれません:-)