私はこの構成を持っています:
RepoA
|-Dir1
RepoB
問題は、RepoBがコピーされてDir1が変更されることです。RepoBの履歴を失うことなくRepoBをRepoAにマージする方法はありますか?
私はこの構成を持っています:
RepoA
|-Dir1
RepoB
問題は、RepoBがコピーされてDir1が変更されることです。RepoBの履歴を失うことなくRepoBをRepoAにマージする方法はありますか?
の履歴を救済する方法は間違いなくあります。RepoB
それが正しく理解されている場合、これは のDir1
下のバージョンを表しRepoA
ます。
まず、RepoB
すべてのファイルがパターンに従って名前が変更されるように、開発ブランチの履歴を書き直すことから始めます* -> Dir1\*
。つまり、最初のコミットに移動し、git mv
すべてのファイルをサブディレクトリに移動してから、他のすべてをリベースします。これは で実行できgit rebase --interactive
ます。に存在しないブランチを作成しRepoA
ます。rescue
それをブランチと呼びましょう。
次に、 と の両方RepoA
をRepoB
共通の祖先に指摘します。RepoA
アップストリームがあるRepoB
場合、.git/config
同じアップストリームを指すように を編集できます。
次に、rescue
ブランチをRepoB
上流に押し込み、 git fetch
inを実行しRepoA
てそれをピックアップします。RepoA
これで資料ができました。
この時点で、 でブランチ コミットを選択して開発ブランチに入れるRepoA
ことができます。rescue
ゼロからの具体的なシナリオ。このセッションでは、repo-a
から複製された を作成しますupstream
。でrepo-a
を作成しdir1/file
ます。次に、新しい git リポジトリrepo-b
を のコピーとして作成しますdir1
。でハッキングを行いfile
ます。次に、ファイルが に移動され、変更が再生されるように履歴を書き換えます。dir/file
これを というブランチで行いますrescue
。upstream
のリモートとして確立し、そこにrepo-b
プッシュrescue
します。次に、 にプルrescue
し、の上repo-a
にリベースしてから、 としてインストールします。rescue
master
rescue
master
注:の履歴書き換えは、rescue
いくつかの手動コマンドを使用してハッキングされました。最初にベースコミットにハードリセットしgit mv
、ファイルをサブディレクトリに移動して、そのルートコミットを修正しました。その後、次のコミットを選択しました。実際には を実行しgit rebase --interactive <root-commit-sha>
ますが、ログに記録されたセッションとして表示するのは困難です。
~$ mkdir upstream
~$ mkdir repo-a
~$ cd upstream
~/upstream$ git init --bare
Initialized empty Git repository in /home/kaz/upstream/
~/upstream$ cd ../repo-a
~/repo-a$ git clone ../upstream .
Cloning into '.'...
done.
warning: You appear to have cloned an empty repository.
~/repo-a$ mkdir dir1
~/repo-a$ cd dir1
~/repo-a/dir1$ cat > file
abc
def
~/repo-a/dir1$ git add file
~/repo-a/dir1$ git commit -m "file added"
[master (root-commit) 1b5cdf9] file added
1 file changed, 2 insertions(+)
create mode 100644 dir1/file
~/repo-a/dir1$ git push origin master
Counting objects: 4, done.
Writing objects: 100% (4/4), 252 bytes, done.
Total 4 (delta 0), reused 0 (delta 0)
Unpacking objects: 100% (4/4), done.
To /home/kaz/repo-a/../upstream
* [new branch] master -> master
さて、ここでばかげた部分が来ます: 誰かが のコピーを作成し、それを とrepo-a/dir1
呼び、それrepo-b
を Git リポジトリとして初期化し、file
バージョン管理下に追加してコミットします:
~/repo-a/dir1$ cd ../..
~$ cp -a repo-a/dir1 repo-b
~$ cd repo-b
~/repo-b$ git init
Initialized empty Git repository in /home/kaz/repo-b/.git/
~/repo-b$ git add file
~/repo-b$ git commit -m "repob"
[master (root-commit) fe0c898] repob
1 file changed, 2 insertions(+)
create mode 100644 file
今、その同じ人が の作業を開始しfile
、それに材料を追加します。
~/repo-b$ cat file
abc
def
~/repo-b$ cat >> file
ghi
~/repo-b$ git diff
diff --git a/file b/file
index 5f5521f..8edb37e 100644
--- a/file
+++ b/file
@@ -1,2 +1,3 @@
abc
def
+ghi
~/repo-b$ git commit -a -m "ghi"
[master 3e35a62] ghi
1 file changed, 1 insertion(+)
今、その人は、「ああ、何をしているのだろう! この切り替えを でrepo-a
、以下でdir1
!」と気づきます。
最初のステップはに接続するrepo-b
ことupstream
です:
~/repo-b$ git remote add origin ../upstream
ここで、 での作業を停止し、 と同じように始まるブランチにmaster
切り替えます。rescue
master
~/repo-b$ git checkout -b rescue
Switched to a new branch 'rescue'
~/repo-b$ git log
commit 3e35a6216f8788cc7a58f7bb84a2dfaf8e47e720
Author: Kaz <kaz@stackoverflow.help.com>
Date: Fri Dec 19 22:17:54 2014 -0800
ghi
commit fe0c898b11124d0174e65b32fdcc956443446dcf
Author: Kaz <kaz@stackoverflow.help.com>
Date: Fri Dec 19 22:17:25 2014 -0800
repob
rescue
ここで、ファイルが の下にあるように の履歴を書き換えますdir1
。まず、ルート コミットにリセットし、名前を変更します。
~/repo-b$ git reset --hard fe0c898b11124d0174e65b32fdcc956443446dcf
HEAD is now at fe0c898 repob
~/repo-b$ mkdir dir1
~/repo-b$ git mv file dir1
~/repo-b$ git commit -a --amend -m "repob"
[rescue e3a6c19] repob
1 file changed, 2 insertions(+)
create mode 100644 dir1/file
ここで、一番上の変更を選択します。dir1/file
名前の変更に続いて、変更は にうまくパッチを適用します。
~/repo-b$ git cherry-pick 3e35a6216f8788cc7a58f7bb84a2dfaf8e47e720
[rescue 7f21bf5] ghi
1 file changed, 1 insertion(+)
~/repo-b$ ls
dir1
~/repo-b$ cat dir1/file
abc
def
ghi
では、レスキュー パッケージを次の場所にプッシュします../upstream
。
~/repo-b$ git push origin rescue
Counting objects: 8, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (2/2), done.
Writing objects: 100% (8/8), 507 bytes, done.
Total 8 (delta 0), reused 0 (delta 0)
Unpacking objects: 100% (8/8), done.
To ../upstream
* [new branch] rescue -> rescue
repo-a
もう一度オフに。そこでgit fetch
、rescue
ブランチとそのオブジェクトを取り込むために を実行します。
~/repo-b$ cd ..
~$ cd repo-a
~/repo-a$ git fetch
remote: Counting objects: 8, done.
remote: Compressing objects: 100% (2/2), done.
remote: Total 8 (delta 0), reused 0 (delta 0)
Unpacking objects: 100% (8/8), done.
From /home/kaz/repo-a/../upstream
* [new branch] rescue -> origin/rescue
ここからは、Git 101 の資料です。rescue
の上にブランチをリベースしmaster
ます。
~/repo-a$ git checkout rescue
Branch rescue set up to track remote branch rescue from origin.
Switched to a new branch 'rescue'
~/repo-a$ git rebase master
First, rewinding head to replay your work on top of it...
Applying: ghi
~/repo-a$ ls
dir1
~/repo-a$ cat dir1/file
abc
def
ghi
~/repo-a$ # YAY!
次に、 に戻りmaster
、 に早送りしrescue
ます。
~/repo-a$ git checkout master
Switched to branch 'master'
~/repo-a$ git reset --hard rescue
HEAD is now at 2546207 ghi
~/repo-a$ cat dir1/file
abc
def
ghi
終わり。