あるリポジトリから別のリポジトリにgitパッチを適用するにはどうすればよいですか?


80

2つのリポジトリがあります。1つはライブラリのメインリポジトリで、もう1つはそのライブラリを使用するプロジェクトです。

従属プロジェクトで修正を加えた場合、そのパッチをアップストリームに適用する簡単な方法が必要です。

ファイルの場所はリポジトリごとに異なります。

  • メインレポ: www.playdar.org/static/playdar.js
  • 事業: playlick.com/lib/playdar.js

git format-patch -- lib/playdar.jsplaylickプロジェクトで使用してgit amから、メインのplaydarリポジトリで使用しようとしましたが、パッチファイル内のファイルの場所が異なるとエラーが発生しました。

特定のファイルの特定のコミットから別の任意のファイルにパッチを適用する簡単な方法はありますか?

ボーナスポイントについては、パッチを適用するファイルがgitリポジトリにない場合はどうなりますか?


回答:


117

パッチファイルを手動で編集することが問題外であるか実行不可能な場合、これは標準オプション(git applygit format-patchおよびGNUで利用可能)を使用して実行できますpatch

  1. -p<n>nパッチ内のパスから先頭のディレクトリを削除します。

  2. 処理後-p、適用する前にパッチ内の各パスの--directory=<root>rootに追加します。

したがって、あなたの例では、元々あったパッチを取得しstatic/playdar.jsて適用するにはlib/playdar.js、次のコマンドを実行します。

$ cat patch_file | git am     \ 
          -p1                 \ # remove 1 leading directory ('static/')
         --directory='lib/'     # prepend 'lib/'

1
このトップアンサーを作るチャンスはありますか?これは、パッチファイルを手動で編集するよりもはるかに簡単です。
ウェストン2017年

確かに、これはより良い/より簡単な答えですが、@ araqnidの答えはまだ知っておくとよいでしょう。
James Wheare 2017年

最初はせずにしようとした後にディレクトリを調整するための関連--directorystackoverflow.com/questions/24121709/...
イオアニスFilippidis

38

によって生成されるパッチgit format-patchは単なるテキストファイルです。別のパスを変更するようにdiffヘッダーを編集できます。

したがって、たとえば、次のようなものが生成されます。

diff --git a/lib/playdar.js b/lib/playdar.js
index 1234567..89abcde
-- a/lib/playdar.js
++ b/lib/playdar.js

に変更lib/playdar.jsstatic/playdar.jsてパッチを実行するだけですgit am"

パッチは、標準のGNUパッチユーティリティで読み取り可能である必要があります。その場合、名前変更パッチのサポートは普遍的ではないため、などのオプションを指定してgit実行format-patchすることはできません。-M-C


1
後でこのページを再訪する…これは、サブモジュールを提案した以前の「勝者」よりも、尋ねられた質問に対するより良い答えです。
James Wheare 2010

4

両方のプロジェクトがgitプロジェクトであると仮定すると、サブモジュールが最適であるように思われます。これにより、gitプロジェクトは別のgitプロジェクトに動的にリンクでき、基本的には別のgitリポジトリ内でgitリポジトリをベイク処理でき、どちらも独自のライフを持​​ちます。

つまり、「プロジェクト」のサブモジュールとして「メインリポジトリ」を追加します。「メインリポジトリ」で新しいものをコミット/プッシュするときはいつでも、git pullそれらを「プロジェクト」に戻すだけです。


うーん、サブモジュールのドキュメントを読んだので、これは「簡単な方法」のようには聞こえませんが、最も堅牢かもしれません。それは私がちょうど含むサブモジュールを作成する必要があるだろうように見えますplaydar.js、その後(私はから他のすべてたくないの両方の他のプロジェクトでこれをインクルードファイルのwww.playdar.org中にplaylick.com、私はちょうど今、正直に言うと、手動でのパッチファイルを編集するために頼るかもしれないプロジェクトを) 。または、2つの間でコピー&ペーストを続けます。乾杯。
James Wheare 2009年

これは明確で徹底的なチュートリアルであり、この質問に出くわした
James Wheare 2009年

2

ヘンリックの答えを完成させ、ボーナスポイントを獲得するには

パッチを適用するファイルがgitリポジトリにない場合はどうなりますか?

gitリポジトリからのパッチの候補ファイルのディレクトリにアクセスできる場合は、最初にそのディレクトリ/ファイルのツリーをgitリポジトリ自体に変換できます。( ' git init':gitリポジトリは結局のところルートディレクトリ内の単なる.gitです)。
次に、そのリポジトリをメインプロジェクトのサブモジュールとして設定します。


2

この--relativeオプションを使用format-patchすると、抽象化を改善できます(パッチの生成元のリポジトリに関する無関係な詳細を非表示にします)。

[repository-with-changes]
git format-patch --relative=(path-to-library) (base-commit-for-patch) ## 'HEAD~1'

--3wayパッチを適用するときに(does not exist in indexエラーを回避するために)オプションが必要であることがわかりました。マイレージは異なる場合があります。使用--directory=(...)が必要になるのは、ターゲットパスがリポジトリのルートでない場合のみです。

[repository-to-update]
git am --3way --directory=(path-to-library) (patch-file)

  • format-patch 'base'以降、現在のブランチへのコミットごとに1つのパッチファイルを作成します。

  • --relativeオプションのドキュメントが欠落している場合もありますが、とにかく機能しているようです(バージョン2.7.4以降)。



1

メインリポジトリを一時的に削除(名前変更)するだけです。

cd to/main/project
mv .git .git_
cd to/sub/project
git apply patchname
cd -
mv .git_ .git

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