web-dev-qa-db-ja.com

まだコミットされていない変更がある場合、hgコマンドラインを使用していくつかのパッチを適用する方法は?

次のコマンドを使用して、コミットせずにMercurialにパッチを適用します。

hg import patch.diff --no-commit

それはうまくいきます、しかし私がこのように一度にいくつかのパッチを適用しようとすると:

hg import patch1.diff --no-commit
hg import patch2.diff --no-commit
...

2回目のコミット後にこのエラーメッセージが表示されます。

abort: uncommitted changes

SourceTreeでまったく同じことを行った場合(patch1、patch2を適用し、[作業コピーファイルを変更]を選択)、2つのパッチが作業コピーに適用され、patch1とpatch2の変更が結合/折りたたまれます一緒。

Hgコマンドラインを使用して同じことをするには?

17
tigrou

これは、Mercurialの作者が設計した動作です。作業コピーにコミットされていない変更を「手動で」行ったとします。hg importがパッチを自動的に適用し、変更とパッチの両方をコミットすることは望ましくありません。誤ったログメッセージで変化し、両方の変化が絡み合っています。

これがhg help importが言う理由です:

Because import first applies changes to the working directory, import will
abort if there are outstanding changes.

Importコマンドは、パッチを適用するだけではなく、変更セットをインポートするためのものです(データがhg exportからのものである場合、metedataを使用)。作業コピーに独自の変更がある場合でも、たとえばhg import --bypassを引き続き使用できます。コミットは作業コピーではなくリポジトリに直接適用されるため、エラーは発生しません。 (注:ただし、変更をコミットするだけの場合、2つのヘッドが表示されます。マージする必要があります.. :-)。

Unixシステムのコマンドラインでの解決策は、hg importの代わりにpatchコマンドを直接使用することです。これは、ローカル変更のチェックが実行されないためです。例えば。、

for i in 1 2 etc.
do 
   patch -p1 < patch$i.diff
done
hg commit ...

非UNIXシステムの場合、shelve拡張機能をインストールしてグローバル構成ファイル(Mercurial.ini)で有効にし、shelveを使用してパッチを次々にマージします:

hg import --no-commit patch1.diff
hg shelve
hg import --no-commit patch2.diff
hg unshelve
etc.

競合が発生した場合は、shelveがそれを検出し、解決する必要があります。その後、shelve--continueオプションで解決されることを伝えます。

お役に立てれば幸いです。

14

これが私のために働いたものです(Windowsソリューション)、アイデアはChristophe Muller回答から取得されました:

copy /b "patch01.diff" + "patch02.diff" + ... + "patchXX.diff" "all.diff"

hg import "all.diff" --no-commit

すべてのパッチを(1つの大きなファイルとして)連結して適用します。

5
tigrou

可能な解決策の1つは Mercurial Queues を使用することです(注-この拡張機能は「廃止予定」と見なされることが多いようですが、まだ非推奨ではなく、Mercurialにプリインストールされています)。

これまでにMQを使用したことがない場合は、少し複雑でも非常に便利です。しかし、それは効果的にパッチのキューを作成することを可能にし、それはプッシュ、ポップ、リオーダーなどが可能です。

次のように問題を解決するのに役立ちます。

:: if you don't already have MQ initialised for the repo, do so
hg init --mq

:: import the patches you want as queue entries
hg qimport -P patch1.diff
hg qimport -P patch2.diff
hg qimport -P patch3.diff

-Pオプションは、インポート時に変更をプッシュします。つまり、変更が正しく適用されることを効果的に確認しています。 MQにすべてのパッチをインポートしたら、それらをすべてポップし(何も適用されず、開始したところに戻ります)、それらをすべて新しい結合パッチに折りたたみます。

:: go back to no patches applied, and create a new patch at the front of the queue
hg qpop --all
hg qnew -m "Your planned commit message" combined_patches
:: fold the named patches into the current one
hg qfold patch1 patch2 patch3

次に、結果のパッチに満足したら、それを「実際の」チェンジセットに変換します。

:: convert combined_patches into a "real" changeset
hg qfinish combined_patches
3
icabod

これを行うためのよりエレガントな方法があると思います。

(最初にリバースパッチを抽出する場合):

hg diff -c xxx --reverse > 1.diff

現在のチップがtxxxであると仮定

hg import 1.diff #creates changeset cxxx1
Hg import 2.diff #creates changeset cxxx2
Hg import 3.diff #creates changeset cxxx3
hg rebase -r cxxx1::cxxx3 -d txxx --collapse
1
Zang XC