11

はい、私は最初からプロジェクトをフォークするべきだったことを知っていますが、これが私が今いる状況です。:)

ローカルコンピューターにブログを含むローカルGitリポジトリがあり、数か月のコミット履歴があります。元々、リポジトリ http://github.com/mojombo/mojombo.github.comからファイルをダウンロードするだけで、ローカルのGitリポジトリを続行し、最初のコミットはmojomboのリポジトリからの最新ファイルのように見えました。

プロジェクトをフォークして、ローカルのGitリポジトリのコミットをその上で再生したいので、プロジェクトを最初からフォークしてから、GitHubのフォークしたバージョンのmojomboのリポジトリにプッシュして戻したようです。アカウント:

http://github.com/program247365/mojombo.github.com

したがって、おそらく履歴は次のようになります。

mobjombo repository:         1---2---3----23
                                  \
my blog repository commits:       24---25---

これを行うために正確に使用できるGitコマンドは何ですか?

私はこの質問を見てきました。mojomboのリポジトリをプロジェクトのリモートとして追加し、それをプルしてマージし、競合を解決してから、GitHubでフォークされたプロジェクトにプッシュする必要がありますか?

4

3 に答える 3

16

要するに:

1 つの解決策は、グラフトを使用して履歴を接続し、 を使用git filter-branchしてこれらのグラフトに従って履歴を書き換え、オプションでマージを実行することです。

元のリポジトリでの新しい開発の上に変更 (コミット) を再生するソリューション (リベースソリューション) は、別の実行可能なソリューションであることに注意してください。


より長いバージョン:

スナップショットをダウンロードしてローカル開発を開始したリポジトリのリビジョンを覚えているか、ソースを調べるか、git コマンドを使用して見つけることができると仮定しましょう。このリビジョンを START または A と呼びましょう。

ローカルの切断された履歴が元のリポジトリのクローンにあると仮定しましょう。これは、ローカルの切断された開発が、プロジェクトの完全な履歴と同じリポジトリにあることを意味します。ローカル ブランチがブランチ 'master' にあると仮定しましょう (簡単にするために、ブランチは 1 つだけです)。

ローカルの切断された作業でプロジェクトをリポジトリにフェッチしなかった場合は、次の方法でこれを行うことができます。

$ git remote add origin git://github.com/mojombo/mojombo.github.com.git
$ git fetch origin

履歴は次のようになります。

*---*---*---*---*---A---*---*---*---* <--- origin/master (リモート追跡ブランチ)

                                     x---y---*---*---* <--- master (ローカル切断履歴)

上の図の A という名前のコミットは、スナップショットとしてダウンロードしてローカル開発を開始した START コミットです。

2 つの可能性があります。最初のコミット 'x' として 'A' のスナップショットをコミットしたか、作成した最初のコミットがローカルの変更でした。

最初のケース ('Initial commit' または 'Import' などの元の開始状態をコミットした場合) では、接続された履歴を次のようにする必要があります。

*---*---*---*---*---A---*---*---*---* <--- origin/master (リモート追跡ブランチ)
                                      \
                                        \-y---*---*---* <--- master (ローカル切断履歴)

つまり、最初の元のコミット 'y' は、'A' を親として持ちます。

2 番目のケース (変更をコミットした場合) では、接続された履歴を次のようにする必要があります。

*---*---*---*---*---A---*---*---*---* <--- origin/master (リモート追跡ブランチ)
                                      \
                                        \-x---y---*---*---* <--- master (ローカル切断履歴)

つまり、最初のコミット 'x' に 'A' を親として持たせたいとします。

どちらの場合も、コミット 'A' の完全な SHA-1 識別子と、コミット 'x' および 'y' の完全な SHA-1 識別子を見つけたいと考えています。

git rev-parseを使用して、コミット 'A' の SHA-1 を見つけることができます (まだ知らないと仮定します) 。

$ git rev-parse A     # or A^{commit}
437b1b20df4b356c9342dac8d38849f24ef44f27

('^{commit}' サフィックスは、コミットSHA-1を見つけたことを確認するために必要になる場合があります。これは、たとえば、'v0.99' などのタグで 'A' を知っている場合に重要です; あなたの場合は問題のリポジトリはタグを使用しないため、必要ありません)。

git rev-listを使用して、コミット「x」および「y」の SHA-1 を見つけることができます(開発がブランチ「master」で行われたと仮定します)。

$ git rev-list --topo-order master | tail -2
8bc9a0c769ac1df7820f2dbf8f7b7d64835e3c68
e83c5163316f89bfbde7d9ab23ca2e25604af290

( " | tail -2" は、生成されたリストで最後の 2 つのコミットを見つけるためにここにあります。持っていない場合は使用する必要はありません)。

注: 上記のすべての例で完全な SHA-1 はであり、そのまま使用しないでください。

'A' (または 'START') を親として持つコミットに FIRST という名前を付けましょう (上記のように、ケースに応じて 'x' または 'y' になります) 履歴を接続するには:

$ echo "<SHA-1 of FIRST> <SHA-1 of START>" > .git/info/grafts

git log --graph次に、gitk、QGit、またはGitX などのグラフィカル履歴ブラウザを使用して、履歴が正しく接続 (結合) されているかどうかを確認する必要がありますgit show-branch

$ gitk master origin/master    # or --all

(ここで gitk は単なる例です。" git show branch" を使用する場合、常に ' --all' オプションを使用できるとは限りません)。

最後に、おそらくこれらの変更を永続的なものにしたいので、リポジトリからフェッチする人は誰でも履歴を接続できます. git filter-branchを使用してこれを行うことができます:

$ git filter-branch master

「refs/original/master」に元の (切断された) 履歴があります。

これで、grafts ファイルを削除できます。

$ rm .git/info/grafts

これで、元のリポジトリの新しい開発にマージできるようになります。

$ git merge origin/master

ブランチごとの構成をセットアップするため、ブランチ 'master' で origin(al) リポジトリの変更をプル (マージ) するときに単に「git pull」を実行するだけで十分です。これは読者の演習として残されています... :- )


注:リベース ソリューションは、次の履歴になります (最初のコミットが単純なインポートである場合を想定しています)。

*---*---*---*---*---A---*---*---*---* <--- origin/master (リモート追跡ブランチ)
                                                                     \
                                                                       \-y'---*'---*'---*' <--- master (ローカル切断履歴)

(ここy'で、コミットyが変更されたことを意味します。ほぼ同じ変更セットである必要がありますが、コミットとは異なります)。

于 2009-09-22T08:09:58.097 に答える
6

試しgit pullたところ、次のエラーが発生しました。

$ git pull grid master:master
! [rejected]        master     -> master  (non fast forward)

私の特定のケースでgit rebaseは、ここの手順で示されているように、それが私のために行く方法であるように見えました:

#Clone my forked project from github
git clone git@github.com:program247365/mojombo.github.com.git 

#Add my repo as a remote repo, with the alias 'grid'
git remote add grid "path/to/remote/gitrep/with/all/history/unrelated/to/mojombo/" 

#Rebase my commits on top of mojombo's
git rebase master grid/master

#Switch to the local master branch 
git checkout master

#Call up my mergetool via git, to start rectifying the conflicts that emerge between my repo, and mojombo's
git mergetool

#Push my rebased/combined repo back to Github.com
git push github
于 2009-09-22T04:13:14.423 に答える
4

ここで、何ができるかについて考えてみます。質問の最後にまとめたアイデアとは逆のようなものです。

  1. GitHub で mojombo のリポジトリをフォークします。
  2. フォークしたコピーを複製します。
  3. 既存の (元の) リポジトリからの変更をマージします。
  4. 元のリポジトリを削除します (必要に応じて、もう必要ありません)。

したがって、基本的には、GitHub でフォークした後、次の一連のコマンドを使用できます。

$ git clone git://github.com/$YOUR_USERNAME/$YOUR_PROJECT.git  # Clone your GitHub fork (#2 from above)
$ git pull /path/to/your/original/repo master:master           # Clone your original repo's master branch into your new repo (cloned from GitHub)
$ rm -rf /path/to/your/original/repo                           # Might as well delete the original -- you don't need it anymore, since all your history is in your new repo

要約すると、このメソッドは、古いレポで行ったすべての変更をマージします (したがって、開発履歴を保持します)。また、モジョンボの履歴を取り込み、モジョンボの変更に遅れずについていくことができます/簡単に変更を彼に戻すことができます該当する場合はレポ。

于 2009-09-21T22:48:38.953 に答える