web-dev-qa-db-ja.com

2つのGitリポジトリをマージして履歴を保持する

私が持っていた別の質問を拡張したいと思います: 2つのGitリポジトリをマージし、マスター履歴を保持します

2つの異なるリポジトリを1つのリポジトリにマージすることに成功しました。これを成功させるにはリベースが必要でした。マスターは正しいですが、マージ履歴も保持したいと思います。これは可能ですか?

2つのリポジトリがあります。

Repo A

Repo B

これはリベース後の結果です。 トップリポジトリの時間はリベース時間です。元の日付が失われました!

Rebase

これは私がそれをした方法です:

# Assume the current directory is where we want the new repository to be created
# Create the new repository
git init

# Before we do a merge, we have to have an initial commit, so we'll make a dummy commit
dir > Read.md
git add .
git commit -m "initial commit"

# Add a remote for and fetch the old RepoA
git remote add -f RepoA https://github.com/DimitriDewaele/RepoA

# Do the same thing for RepoB
git remote add -f RepoB https://github.com/DimitriDewaele/RepoB

# Rebase the working branch (master) on top of repoB
git rebase RepoB/master

# Rebase the working branch (master with RepoB) on top op repoA
git rebase RepoA/master

このようなものを持つことは可能ですか?painted solution !!!

Painted

元の時間とマージ履歴を保持したいと思います。

UPDATE-ANSWER

私にとって最も効果的だった答えは、グラフトポイントでの作業でした。しかし、他の回答も他のユースケースで非常に役立ちます。結果をgithubに追加したので、誰でも評価できます。

回答1:私の場合はうまくいきます「graft」は私にとって正しい動作する答えを明らかにしました。

GitHub:RepoGraft

enter image description here

Answer 2 "LeGEC"の "replace"オプションも、いくつかのユースケースで良い結果をもたらします。 1つの異常が残りました。

GitHub:RepoHistory

enter image description here

回答3:追加する価値 'VonC'からの回答。私の場合、オプション「--preserve-merges working」を取得できませんでした。これは他のシナリオでも機能するかもしれませんが、私はこのファーターをテストしませんでした。

16
Dimitri Dewaele

ご存じのとおり、rebaseは履歴をつなぎ合わせるために使用するコマンドではありません(実際に履歴を書き換えるため)。初期のGitには、あなたがやろうとしていることのために特別に設計された機能(ハック)がありました: graft points 。さらに良いことに、1.6.5以降では、代わりに git replace --graft を使用できます。

git checkout master
git replace --graft $(git log RepoB/master --format=%H | tail -1) HEAD
git replace --graft $(git log RepoA/master --format=%H | tail -1) RepoB/master
git reset --hard RepoA/master

git log RepoA/master --format=%H | tail -1RepoAから最初のコミットを返します)

技術的には、replaceにまだ価値のあるものがなければ、最初のmasterをスキップして、RepoB + RepoAの履歴のみを生成することができます。

これらのコマンドはrefs/replace/*にエントリを作成し、プッシュおよびプルして、変更した履歴を他のユーザーと共有できます。または、RepoA/RepoBのSHAを保持する必要がない場合は、git filter-branch --allを実行して、置換を永続化できます。希望する系統の「実際の」コミットのセット。

10
dahlbyk

Git rebaseには2つのオプションがあります。

p
--preserve-merges

マージコミットが導入するコミットを再生して履歴を平坦化する代わりに、マージコミットを再作成します。

--committer-date-is-author-date 

(から git am

デフォルトでは、コマンドは電子メールメッセージの日付をコミット作成者の日付として記録し、コミットの作成時刻をコミッターの日付として使用します。これにより、ユーザーは、作成者の日付と同じ値を使用して、コミッターの日付を偽ることができます。

2番目のリベースがより良い結果をもたらさないかどうかをテストします。

git rebase -p --committer-date-is-author-date RepoA/master
1
VonC

この回答は、RepoBをアクティブなリポジトリとして使用し、RepoA履歴に引き続きアクセスする別の方法を提案しています。

使用する git replace

# start with a regular clone of the active repo :
$ git clone RepoB

# add repoA as a remote :
$ git remote add -f history https://github.com/DimitriDewaele/RepoA

# get hash of *initial* commit on repoB :
$ git log --oneline Origin/master | tail -1
abcdef Initial commit

# get hash of last commit on repoA :
$ git log --oneline history/master | head -1
12345 Merge branch 'develop'

# use 'git replace' to tell git to stitch histories in the log :
$ git replace abcdef 12345

注:この操作は、リモートリポジトリではなく、ご使用のマシンで行われるため、すべての新しいクローンで繰り返す必要があります。

バリアント

プッシュできますRepoA:masterからRepoBへの新しい名前(例:RepoB:history/master)の場合、git replace abcdef history/master、すべてRepoBに保存されているコミット。

1
LeGEC