1

質問までの手順

私の質問に至るまでに私がしたことは次のとおりです。

  1. Githubでプロジェクトをフォークし、ローカルに複製しました
  2. バグを修正するために、ローカル リポジトリに 2 つのコミットを行いました
  3. これらの 2 つのコミットをフォークした Github リポジトリにプッシュしました
  4. 元のレポ所有者に Github 経由でプル リクエストを送信しました
  5. 元の所有者がバグを解決するために別のコミットを行った

質問

元の所有者のコミットをマージして、ローカル マスターが彼のマスターと同一になるようにするにはどうすればよいですか (基本的に、Github 早送りを実行したい)、新しいブランチで作成した 2 つのコミットを保持するにはどうすればよいですか?

疑問が頭に浮かんだ後の手順

これまでに私が行ったことは次のとおりです(私がやりたいことを達成するために行う必要があると思います):

  1. 元のリポジトリをリモートとして追加:git remote add original-repo git://github.com/blah/blah.git
  2. 元のレポを取得しました:git fetch original-repo
  3. 元のレポ マスターを取得しました。git fetch original-repo master
  4. ヘッドライトモードで鹿に入ったので、グーグルで失敗した後、Stackoverflowに質問を投稿しました。Stackoverflow にも同様の質問がいくつかありますが、同じことを達成しようとしているものは見当たりませんでした。
4

2 に答える 2

2

「現在のブランチですべての変更を行い、Git の新しいブランチに移動する」という質問に少し似ています。

基本的に、マスター ブランチをコミット前の状態にリセットし、それらを新しいブランチ 'myBranch' (または任意の名前) に配置する必要があります。

$ git checkout -b myBranch SHA1_before_your_commits
$ git rebase master # to replay all your commits on top of this new branch
$ git checkout master
$ git reset --hard SHA1_before_your_commits

次に、元のリポジトリからコミットを追加します。

$ git pull original-repo master

次に、GitHub のフォークされたリポジトリへのプッシュを強制する必要があります (ブランチの履歴を書き直したため)。

 git push --force origin master 

警告: これは、リモートの履歴を破壊するだけでなく、同じリモートから更新する人にエラー メッセージを表示する可能性もあります (書き換える履歴の量によって異なります)。これは最後の手段としてのみ使用してください。

ここで、フォークされたリポジトリを誰もクローンしていない場合、これは実行可能なソリューションになる可能性があります。

于 2009-09-23T16:54:49.787 に答える
1

VonCによって提示されたものに代わる解決策は、「私たちの」マージ戦略を使用して履歴を結合することですが、1 つのバージョンを取ることです。

$ git checkout -b tmp original-repo/master
$ git merge -s ours master  # take version from 'tmp', i.e. from 'original-repo/master'
$ git checkout master
$ git merge tmp                    # should be fast forward
$ git branch -d tmp              # 'tmp' branch is no longer needed

上記で行うことは、要するに「彼らの」マージを行うことです。

警告:このソリューション は、最後のマージ (最後の更新) 以降、ローカル ブランチに他のコミットがない場合にのみ、元の問題を解決します。

したがって、このソリューションでは、問題を解決したバージョンを履歴に残すことができますが、アプリケーションがより制限されます。


以下は、各ステップでリポジトリで何が起こっているかを示す一連の ASCII アート図です。

  1. 最初のコマンドの前:
    \*---\*---x---A <-- original-repo/master (リモート追跡ブランチ)
                    \
                      \\--a---b <-- マスター <-- HEAD
    
  2. " git checkout -b tmp original-repo/master" の後:
                                              <-- 元のレポ/マスター、
    *---*---x---A <-- tmp <-- HEAD
                    \
                      \--a---b <-- マスター
    
    ここで、「tmp」(ローカル ブランチ) と「original-repo/master」(リモート追跡ブランチ) の両方が同じコミットを指しています。
  3. " git merge -s ours master" の後:
                            /-------------- 元のレポ/マスター
                          v
    *---*---x---A----A' <-- tmp <-- HEAD
                    \ /
                      \--a---b <-- マスター
    
    ここで、コミット A' はマージ コミットですが、コミット A と同じ内容 (同じツリー) です。
  4. " git checkout master && git merge tmp" の後 (マージは早送りする必要があります):
                              /-------------- 元のレポ/マスター
                            v
    *---*---x---A----A' <-- tmp,
                    \ / <-- マスター <-- HEAD
                      \--a---b
    
    「マスター」と「tmp」の両方が同じコミットを指しています。
  5. " git branch -d tmp" の後、および図の再編成
    \*---\*---x---A-----\ <-- 元のリポジトリ/マスター
                    \ \
                      \\--a---b---A' <-- マスター <-- HEAD
    

最後に:

  • リモート追跡ブランチ ' original-repo/master' (すなわち ' refs/remotes/original-repo/master') はコミット A を指し、
  • 現在のブランチであるローカル ブランチ ' master' (つまり ' refs/heads/master') は、コミット A' を指しています。
    コミット A' には次のものがあります。
    • A を最初の親 ( A'^1 == A) としてコミットし、
    • b を 2 番目の親としてコミット ( A'^2 == a)、
    • その内容 (ツリー) はコミット A ( A'^{tree} == A^{tree}) と同じです。
于 2009-09-24T10:01:49.277 に答える