別の名前とパスのファイルにGitパッチを適用する方法は?


100

2つのリポジトリがあります。1つは、ファイルに変更を加えることです./hello.test。変更をコミットし、そのコミットからパッチを作成しgit format-patch -1 HEADます。これで、hello.testと同じ内容のファイルを含む2つ目のリポジトリがありますが、別のディレクトリに別の名前で配置されています./blue/red/hi.test。前述のパッチをhi.testファイルに適用するにはどうすればよいですか?私は試しましgit am --directory='blue/red' < patch_fileたが、もちろんファイルに同じ名前が付いていないと不平を言っています(Gitは気にしていないと思いましたか?)。おそらくその特定のファイルに適用するためにdiffを編集できることはわかっていますが、コマンドソリューションを探しています。


回答:


97

を使用してパッチを作成git diffしてから、patchユーティリティを使用してパッチを適用できます。これにより、差分を適用するファイルを指定できます。

例えば:

cd first-repo
git diff HEAD^ -- hello.test > ~/patch_file

cd ../second-repo
patch -p1 blue/red/hi.test ~/patch_file

7
ああ、いい、それは考えなかった。しかし、Gitコマンドでこれを行って、コミットデータ(日付と時刻、コミットの作成者、コミットメッセージ)を同じに保つ方法はありますか?
mart1n 2013年

2
amまたはapplyでできることはあるかもしれませんが、見つかりません。変更が頻繁に重複している場合は、サブモジュールを使用するか、選択した言語がコードを共有するために提供しているより優れたソリューションがある可能性があります(たとえば、Rubyでは、重複したコードをgemとして抽出できます)。
georgebrock 2013年

1
これは実際にはドキュメント関連です(ソースファイルはXMLです)。既存のインフラストラクチャでサブモジュールを強く主張する必要があるため、サブモジュールは実際にはオプションではありません。
mart1n 2013年

52

手動パッチ編集や外部スクリプトを含まない簡単な解決策があります。

最初のリポジトリで(これはコミットの範囲もエクスポートする-1場合があります。1つのコミットのみを選択する場合に使用します):

git format-patch --relative <committish> --stdout > ~/patch

2番目のリポジトリ:

git am --directory blue/red/ ~/patch

--relativein を使用する代わりに、同様の質問への回答で述べたように、オプションのin git format-patchを使用してパッチのパスからディレクトリを削除することも-p<n>できます。git amn

git format-patch --relative <committish>なしで実行することもでき--stdout、一連の.patchファイルが生成されます。これらのファイルは、その後に直接供給することができるgit amgit am --directory blue/red/ path/to/*.patch


9
これはまだファイル名が同じであるという事実に依存していますよね?
mart1n 2015

3
この--directoryオプションでは、リポジトリのルートからの相対ディレクトリのフルパスを指定する必要があるようです。--directory=./リポジトリのサブディレクトリにchdirしたときのようなものは機能しません。
Reid

1
使用する--3wayのに役立ちますdoes not exist in indexgit am --3way --directory (relative-path) (patch)
ブレントBradburn

-k両方のコマンドでkeyを使用して、コミットメッセージの最初の行を削除しません。
ruvim 2018

使用する--3wayと役立つだけでなく、(@nobarによって尖ったアウトなど)のエラー「インデックスには存在しない」、だけでなく、きれいにハンドルマージの競合にあなたを可能にします。競合するファイルをそのまま残すのではなく、競合ブロックを追加して解決できます。
ダニエルウルフ

11

これを行うスクリプトで自分の質問に答える:https : //github.com/mprpic/apply-patch-to-file

パッチファイルを手動で変更するのではなく、ターゲットファイルの入力を求め、パッチを変更して、現在のリポジトリに適用します。


5

@georgebrockの回答に基づいて、ここに私が使用した解決策があります:

まず、通常どおりにパッチファイルを作成します(例:)git format-patch commitA..commitB

次に、ターゲットリポジトリがクリーンであること(変更または追跡されていないファイルがないこと)を確認し、次のようにパッチを適用します。

cd second-repo
git am ~/00*.patch

すべてのパッチファイルについて、「エラー:XYZがインデックスに存在しません」などのエラーが発生します。これで、このパッチファイルを手動で適用できます。

patch --directory blue/red < ~/0001-*.patch
git add -a
git am --continue

各パッチファイルに対してこれらの3つの手順を実行する必要があります。

これにより、特別なgit format-patchコマンドやパッチファイルの編集を必要とせずに、元のコミットメッセージなどが保持されます。


1
良い答えです。これは、あらゆる種類の「非標準」パッチ操作の最良の基盤だと思います。私は3つのステップでそれを行います。(1)テキストにコミット - git format-patch -1 commitA --stdout > thing.diff; (2)必要なことを実行するまでパッチファイルを編集します(3)コミットするテキスト。 git am --3way thing.diffパッチのクリーンに適用する部分を受け入れ、適用gitしない部分にはの標準の競合解決プロセスを使用できるという利点があります。
私たちは全員モニカです

2

あなたの状況では2つのファイルはまったく同じであるため、パッチは成功する可能性があります。

ただし、類似しているが完全に同じではないファイルにパッチを適用する場合、または対話型パッチを適用する場合は、3方向マージを使用します。

Fileを変更したAとしましょう。A~1前のバージョンとして示し、A~1to Aとdiff をFile に適用するとしますB

たとえば、Beyond Compareなどの3方向マージツールを開きます。左側のパネルのパスはA、中央のパネルは共通の祖先なので、パスはA~1、右側のパネルのパスはBです。次に、下のパネルにA~1to Aとfileの差分を適用した結果が表示されますB

次の図は、このアイデアを示しています。

ここに画像の説明を入力してください


0

参考:最近、Githubからパッチをダウンロードしてローカルファイルに適用しようとして問題が発生しました(これは新しい場所での「上書き」でした)。

git amファイルが「インデックスにない」または「ダーティ」だったため、パッチは適用されませんでした。しかし、簡単なpatchコマンドでパッチを適用できることがわかりました。パッチを適用するファイルの名前を入力するように求められました。

とにかく仕事が終わった...

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.