web-dev-qa-db-ja.com

あるリポジトリから別のリポジトリにgitパッチを適用する方法は?

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

下位のプロジェクトで修正を行う場合、そのパッチを上流に簡単に適用したいのですが。

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

  • メインリポジトリ:www.playdar.org/static/playdar.js
  • プロジェクト:playlick.com/lib/playdar.js

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

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

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

74
James Wheare

パッチファイルの手動編集が問題外または実行不可能な場合は、標準オプション(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/'
101
vergenzt

_git format-patch_によって生成されるパッチは単なるテキストファイルです。差分ヘッダーを編集して、異なるパスを変更できます。

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

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

必要なのは、_lib/playdar.js_を_static/playdar.js_に変更してから、_git am"_を介してパッチを実行するだけです。

パッチは、標準のGNUパッチユーティリティでgitを持たないが、_format-patch_を_-M_、_-C_などのオプションは、その場合に名前変更パッチを生成します。これらのサポートはユニバーサルではないためです。

37
araqnid

両方のプロジェクトがgitプロジェクトであると仮定すると、 submodules が最適だと思われます。これにより、gitプロジェクトは別のgitプロジェクトに動的にリンクし、本質的に別のgitリポジトリ内にgitリポジトリを作成します。両方とも独自のライフを持​​ちます。

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

4
Henrik Paul

Henrik's answer を完了し、ボーナスポイントを獲得するには

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

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

2
VonC

新しいリモートを追加して、そこからプルできます。 詳細が記載された記事

$ cd <path-to-repoB>
$ git remote add repoA <git-URL-for-repoA>
$ git pull repoA
1
Der_Meister

_--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以降)。

0
nobar

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

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

サブツリーはあなたの問題の最善の解決策だと思います

チュートリアル1

チュートリアル2

0
Mauro