[解決済み] サブディレクトリの git リポジトリをマージする
質問
リモート git リポジトリを、作業中の git リポジトリのサブディレクトリとしてマージしたいと思います。出来上がったリポジトリには、2つのリポジトリのマージされた履歴が含まれ、またマージされたリポジトリの各ファイルがリモートリポジトリにあったような履歴を保持するようにしたいと思います。で述べられているようにサブツリー戦略を使用してみました。 サブツリー マージ戦略の使用方法 にあるようにサブツリー戦略を使用してみましたが、この手順を実行すると、結果として得られるリポジトリには確かに 2 つのリポジトリのマージされた履歴が含まれますが、リモートから来る個々のファイルは履歴を保持していません(それらのいずれかに `git log' を実行すると、" Merged branch..." というメッセージが表示されるだけです)。
また、私はサブモジュールを使用したくありません。なぜなら、2 つの結合された git リポジトリがもう別々であって欲しくないと思っているからです。
リモートリポジトリから来る個々のファイルがその履歴を保持したまま、サブディレクトリとして別のリポジトリにリモートgitリポジトリをマージすることは可能ですか?
どんな助けにも非常に感謝します。
EDITです。 現在、マージされたリポジトリの履歴を書き換えるために git filter-branch を使用する解決策を試しています。うまくいっているように見えますが、もう少しテストする必要があります。私の発見を報告するために戻ってきます。
編集 2: 私が git のサブツリー戦略で使用した正確なコマンドを示すことで、私自身がより明確になることを願っています。 現在作業している git リポジトリを A とし、そのサブディレクトリとして A に組み込みたい git リポジトリを B とします。それは次のようなものでした。
git remote add -f B <url-of-B>
git merge -s ours --no-commit B/master
git read-tree --prefix=subdir/Iwant/to/put/B/in/ -u B/master
git commit -m "Merge B as subdirectory in subdir/Iwant/to/put/B/in."
これらのコマンドの後、subdir/Iwant/to/put/B/in ディレクトリに移動すると、B のすべてのファイルが表示されますが
git log
はコミットメッセージ "Bをsubdir/Iwant/to/put/B/inのサブディレクトリとしてマージする." を表示するだけで、Bにある彼らのファイル履歴は失われています。
何 は が動作するように見えるのは(gitの初心者なので間違っているかもしれませんが)以下のようなものです。
git remote add -f B <url-of-B>
git checkout -b B_branch B/master # make a local branch following B's master
git filter-branch --index-filter \
'git ls-files -s | sed "s-\t\"*-&subdir/Iwant/to/put/B/in/-" |
GIT_INDEX_FILE=$GIT_INDEX_FILE.new \
git update-index --index-info &&
mv "$GIT_INDEX_FILE.new" "$GIT_INDEX_FILE"' HEAD
git checkout master
git merge B_branch
上のfilter-branchのコマンドは
git help filter-branch
から取ったもので、サブディレクトリのパスを変更しただけです。
どのように解決するのですか?
何が起こっているかについての詳細な説明を受けた後、私はそれを理解し、いずれにせよ一番下に回避策があります。 具体的には、私は、リネーム検出が --prefix によるサブツリー マージに惑わされていることが原因だと考えています。 以下は私のテストケースです。
mkdir -p z/a z/b
cd z/a
git init
echo A>A
git add A
git commit -m A
echo AA>>A
git commit -a -m AA
cd ../b
git init
echo B>B
git add B
git commit -m B
echo BB>>B
git commit -a -m BB
cd ../a
git remote add -f B ../b
git merge -s ours --no-commit B/master
git read-tree --prefix=bdir -u B/master
git commit -m "subtree merge B into bdir"
cd bdir
echo BBB>>B
git commit -a -m BBB
git ディレクトリ a と b を作成し、それぞれにいくつかのコミットを入れておきます。 サブツリーのマージを行い、そして新しいサブツリーで を行い、新しいサブツリーで最終的なコミットを行います。
実行中
gitk
(z/a)を実行すると、履歴が表示されることがわかります。 実行中
git log
を実行すると、履歴が表示されることがわかります。 しかし、特定のファイルを見るには問題があります。
git log bdir/B
さて、私たちができるトリックがあります。 特定のファイルのリネーム前の履歴を --follow を使って見ることができるのです。
git log --follow -- B
. これは良いことですが、マージ前の履歴とマージ後の履歴をリンクすることに失敗しているので、あまり良くありません。
M と -C で遊んでみましたが、特定の 1 つのファイルを追跡させることはできませんでした。
ですから、解決策は、サブツリーのマージの一部として行われるリネームについてgitに伝えることだと感じています。 残念ながら、git-read-tree はサブツリーのマージについてかなりうるさいので、一時ディレクトリを通して作業する必要がありますが、コミットする前にそれを取り除くことができます。 その後で、完全な履歴を見ることができます。
まず、"A" リポジトリを作成し、いくつかのコミットを行います。
mkdir -p z/a z/b
cd z/a
git init
echo A>A
git add A
git commit -m A
echo AA>>A
git commit -a -m AA
次に、"B" リポジトリを作成し、いくつかのコミットを行います。
cd ../b
git init
echo B>B
git add B
git commit -m B
echo BB>>B
git commit -a -m BB
そして、これを実現するためのコツは : サブディレクトリを作成し、その中にコンテンツを移動することで、Gitにリネームを認識させることができます。
mkdir bdir
git mv B bdir
git commit -a -m bdir-rename
リポジトリ "A"に戻り、"B"の内容をフェッチしてマージします。
cd ../a
git remote add -f B ../b
git merge -s ours --no-commit B/master
# According to Alex Brown and pjvandehaar, newer versions of git need --allow-unrelated-histories
# git merge -s ours --allow-unrelated-histories --no-commit B/master
git read-tree --prefix= -u B/master
git commit -m "subtree merge B into bdir"
マージされたことを示すために
cd bdir
echo BBB>>B
git commit -a -m BBB
全履歴が連結鎖で保存されていることを証明する。
git log --follow B
このようにすると履歴が残りますが、問題は、古い "b" レポを実際に維持していて、時々そこからマージしている場合(実際には第三者が別途管理しているレポだとします)、その第三者はリネームを行っていないため問題が発生することです。 新しい変更をリネームしたbのバージョンにマージしなければなりませんが、これがスムーズにいかないことが心配です。 しかし、b が消えてしまうのであれば、あなたの勝ちです。
関連
-
[解決済み] Git で直近のローカルコミットを取り消すには?
-
[解決済み] Gitブランチをローカルやリモートで削除するには?
-
[解決済み] git pull」と「git fetch」の違いは何ですか?
-
[解決済み] コミット前に 'git add' を取り消すにはどうすればよいですか?
-
[解決済み] Git リポジトリを以前のコミットに戻すにはどうすればよいですか?
-
[解決済み] Git リポジトリでのマージの衝突を解決するには?
-
[解決済み] 2 つの Git リポジトリをマージする方法は?
-
[解決済み] サブディレクトリを別のGitリポジトリに切り離す(移動する)。
-
[解決済み】"git pull" でローカルファイルを強制的に上書きするには?
-
[解決済み】ローカルのGitブランチの名前を変更するには?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[git push] 解決策: ! [リモート拒否] master -> master (受信前のフックは拒否されました)
-
解決策 このリポジトリでは、別の git プロセスが実行されているようです。たとえば、「git commit」によって開かれたエディタなどです。
-
hint: 現在のブランチの先端が hint: そのリモートカウントより遅れているため、更新が拒否されました。
-
なぜこのマージが必要なのかを説明するコミットメッセージを git に入力してください。
-
[解決済み】既存のGitリポジトリを別のリポジトリにインポートする方法は?
-
[解決済み] キーフィンガープリントが原因でHerokuにプッシュできない
-
[解決済み] チェリーピックのコンフリクトを解決するにはどうしたらいいですか?
-
[解決済み] 新サーバーへのGitプッシュ/クローン
-
[解決済み] Gitでは、これらの言葉はどのような意味ですか?リポジトリ、フォーク、ブランチ、クローン、トラック?
-
[解決済み] gitは "サイレントモード "で動作しますか?