サブディレクトリの変更のみをローカルGitブランチからリモートGitブランチにマージすることは可能ですか、それとも「オールオアナッシング」ですか?
たとえば、私は持っています:
branch-a
- content-1
- dir-1
- content-2
そして
branch-b
- content-1
- dir-1
- `content-2
branch-adir-1の内容をbranch-bdir-1の内容とマージしたいだけです。
サブディレクトリの変更のみをローカルGitブランチからリモートGitブランチにマージすることは可能ですか、それとも「オールオアナッシング」ですか?
たとえば、私は持っています:
branch-a
- content-1
- dir-1
- content-2
そして
branch-b
- content-1
- dir-1
- `content-2
branch-adir-1の内容をbranch-bdir-1の内容とマージしたいだけです。
回答:
SOの質問「選択したファイルをgit-mergeでどのようにマージしますか?」の代わりに、git read-treeに基づいてサブディレクトリ全体をマージするのにより適したこのGitHubスレッドを見つけました:
- 私のリポジトリ=>
cookbooks
私のリポジトリのターゲットディレクトリ=>cookbooks/cassandra
- リモートリポジトリ=>
infochimps
マージしたいリモートリポジトリソースcookbooks/cassandra
=>infochimps/cookbooks/cassandra
これらをマージするために使用したコマンドは次のとおりです
- リポジトリを追加してフェッチします
git remote add -f infochimps git://github.com/infochimps/cluster_chef.git
- マージを実行します
git merge --allow-unrelated-histories -s ours --no-commit infochimps / master
(これは-s ours
、ソースブランチからの変更を破棄する「ours」戦略()を使用してマージを実行します。これinfochimps/master
は、ターゲットブランチ内のファイルを実際に変更せずに、マージされたファクトを記録します)
- マージのみ
infochimps/cookbooks/cassandra
にcassandra
git read-tree --prefix = cassandra / -u infochimps / master:cookbooks / cassandra
これにより、必要なソースサブディレクトリ、つまりソースリポジトリのcookbooks/cassandra
アップストリームブランチのみのツリーが読み取られます。
ターゲットサブディレクトリ名もcookbooks/cassandra
、である必要があることに注意してください。そうしないと、次のように表示されます。
fatal: Not a valid object name
- 変更をコミットする
git commit -m'infochimpscassandraにマージ '
それは奇妙です、[私を編集してください] —しかし、read-tree
ステップはおそらく次のように失敗する可能性があります:
error: Entry 'infochimps/cookbooks/cassandra/README' overlaps with 'cookbooks/cassandra/README'. Cannot bind.
...両方のファイルが同一の場合でも。これは役立つかもしれません:
git rm -r cassandra
git read-tree --prefix=cassandra/ -u infochimps/master:cookbooks/cassandra
しかしもちろん、これがあなたが望むことをすることを手動で確認してください。
<rev>:<path>
、例えばHEAD:README
、:README
、master:./README
git read-tree
ステップは私のために失敗しますerror: Entry 'foo/bar/baz.php' overlaps with 'bar/baz.php'. Cannot bind.
overlaps with
上記のエラーも表示されます。それはどれほど奇妙ですか?
infochimps/master
ますが、ターゲットブランチのファイルを実際に変更することはありません。次のステップでgit read-tree --prefix=cassandra
変更を行うためです。最後のコミットでは、実際の「マージ」コンテンツが記録されます。
私の例では、ブランチ 'source'とブランチ 'destination'があり、どちらも自身のアップストリームバージョンを反映し(ローカルのみの場合はそうではない)、最新のコードにプルされていると仮定します。'source'ブランチにのみ存在するnewFeatureというリポジトリのサブディレクトリが必要だとしましょう。
git checkout destination
git checkout source newFeature/
git commit -am "Merged the new feature from source to destination branch."
git pull --rebase
git push
それは私が見た他のすべてのものよりもかなり複雑ではなく、これは私にとって完璧に機能しました、ここにあります。
これは「実際のマージ」ではないため、宛先ブランチにnewFeatureに関するコミット情報はなく、そのサブディレクトリ内のファイルへの変更のみが含まれることに注意してください。しかし、おそらくブランチ全体を後でマージするか、破棄するので、それは問題ではないかもしれません。
これはEclipseのフォーラムスレッドから入手しましたが、魅力のように機能しました。
git checkout source-branch
git checkout target-branch <directories-or-files-you-do-**NOT**-want>
git commit
git checkout target-branch
git merge source-branch
checkout
フォルダを同じにします=>違いはcheckout
フォルダを削除するだけです=>merge
違いです。それは有効な戦略です。
彼らは二つの枝を持っていますが、唯一の歴史をマージしたいOPのシナリオを考えるとDIR-1をから分岐への分岐B:
# Make sure you are in the branch with the changes you want
git checkout branch-a
# Split the desired folder into its own temporary branch
# This replays all commits, so it could take a while
git subtree split -P dir-1 -b temp-branch
# Enter the branch where you want to merge the desired changes into
git checkout branch-b
# Merge the changes from the temporary branch
git subtree merge -P dir-1 temp-branch
# Handle any conflicts
git mergetool
# Commit
git commit -am "Merged dir-1 changes from branch-a"
# Delete temp-branch
git branch -d temp-branch
ブランチaとブランチbの両方を含むGitリポジトリを作成します。
git checkout branch-a
git diff branch-b dir-1 > a.diff
patch -R -p1 < a.diff
git cherry-pick
必要なコミットを選択し、これらのコミットのみをマージするために使用します。ここでの重要な秘訣は、これらのコミットを簡単な方法で取得することです(Gitログを手動でチェックして手動で入力することでコミットを把握する必要がないようにするため)。方法は次のとおりです。次のようgit log
に、コミットのSHA-1IDを出力するために使用します。
git log ^<commit-a> <commit-b> --pretty=format:"%h" --reverse -- <subdir>
'commit-a'は、マージするブランチの開始点の直前のコミットであり、 'commit-b'は、マージするブランチの最後のコミットです。'--reverse'は、後でチェリーピッキングを行うために、これらのコミットを逆の順序で出力します。
次に、次のようにします。
git cherry-pick $(git log ^<commit-a> <commit-b> --pretty=format:"%h" --reverse -- <subdir>)
シンプルで安定した2つのステップです!
Two steps, simple and stable!
まったく単純ではありません:)
git
であり、それはひどいインターフェースと謎とランダムな名前と意味でいっぱいのひどいメンタルモデルを持っています。