8

リモート+ローカルブランチにコミットがあり、そのコミットを履歴から破棄して、それらの一部を独自のブランチに配置したいと思います。

基本的に、今私は持っています:

           D---E---F---G master

そして私は欲しい:

             E---G topic
            /
           D master

これは、私のローカルリポジトリと(オリジンと呼ばれる1つだけ)リモートリポジトリの両方にあるはずです。

それを取得するための最もクリーンな方法はどれですか?

また、そのリポジトリのクローンを作成し、マスターブランチをチェックアウトした人もいます。リモートリポジトリでこのような変更を行う場合、「git pull」はそれらが同じ状態になるように機能しますか?

4

3 に答える 3

7

あなたが公開したなら、あなたはあなたがの歴史を書き直したくないということは正しいですmasterD他のユーザーが自分の作業を簡単にマージまたはリベースできるように、現在の履歴を保持しながらマスターへのコミットを公開して、現在の状態に戻すことが必要です。

将来のある時点でマージtopicすることを計画してmasterいる場合、おそらくまた実行したいのは、との間に新しい共通ベースを作成することmasterですtopic。これにより、後でマージするときに、topicで元に戻されたコミットが失われることはありませんmaster。これを行う最も簡単な方法は、元の状態にリセットされる「undo」コミットの上に「redo」コミットを作成し、その上masterに新しいtopicブランチを作成することです。

# checkout master branch (currently at G)
git checkout master

# Reset the index to how we want master to look like
git reset D

# Move the branch pointer back to where it should be, leaving the index
# looking like D
git reset --soft HEAD@{1}

# Make a commit (D') for the head of the master branch
git commit -m "Temporarily revert E, F and G"

# Create the new topic branch based on master.
# We're going to make it on top of master and the 'undo'
# commit to ensure that subsequent merges of master->topic
# or topic->master don't merge in the undo.
git checkout -b topic

# Revert the undo commit, making a redo commit (G').
git revert HEAD

別の方法として、コミットE'、F'、G'を個別にやり直すこともできますが、E、F、Gはすでに公開された履歴に含まれているため、'undo'コミットを参照して、次のように言うと、おそらくより理解しやすくなります。コミットは取り消されています。とにかく、これは何をするかgit revertです。

基本的にあなたが知っているのはこれです。

D -- E -- F -- G -- D'      <-- master
                     \
                      \
                        G'  <-- topic

重要なことは、履歴を書き直しておらず、トピックがマスターに基づいているため、マージによって誤って「元に戻す」コミットが適用されないことです。これで、とリモートリポジトリの両方masterを安全にプッシュできます。topic

于 2009-10-06T18:12:16.987 に答える
4

必要に応じて履歴を書き換えることができますが、他の誰かが履歴のコピーを持っている場合はお勧めできません。この場合、おそらくインタラクティブなリベースを使用しますgit rebase -i master topic。これにより、マスターからトピックまでのコミットのリストと、それらを操作する方法に関するヒントが表示されます。削除したいコミットを含む行を削除する必要があります。

そうは言っても、他の誰かがこの歴史を持っているなら、これをするのは無責任であることを強調しなければなりません。中央リポジトリに強制的にプッシュする必要があり、他のすべての人はリポジトリを修正して一致させる必要があります。状況に応じて、比較的単純または複雑になる可能性があります。

git-rebaseのmanページには、「アップストリームリベースからの回復」と呼ばれるすばらしいセクションがあり、実際にそうすることにした場合は、これに対処する方法について説明しています。

編集:

単純な履歴の場合、一般的なシナリオは、中央リポジトリ()への非早送りプッシュを強制した後push -f、他の開発者は次のようになります。

  • 古いマスターをバックアップします。git branch -m master master_old
  • 更新を取得し、オリジンからマスターを再作成します。git remote update origin; git branch master origin/master
  • すべてのトピックブランチを新しいマスターにリベースします。git rebase --onto master master_old topic

まだ元になっていないマスターブランチで作業を行っている場合はこの作業とすべてのトピックブランチをマスターの新しい位置にリベースして、より凝ったものにする必要があります。他の人が持っている歴史を書き直します。実際、何かが公開リポジトリに渡されたら、それを進行中の作業ではなく、ハードかつ高速に記録された履歴と見なす必要があります。

于 2009-10-06T16:50:54.017 に答える
-3

git stashはかなり役に立ちます

ただそれを隠して、二度とそれを見ないでください。

于 2010-04-30T06:36:06.527 に答える