web-dev-qa-db-ja.com

他の変更をそのままにして、単一のファイルをコミットしてプッシュする最も簡単な方法は何ですか?

私は比較的Mercurialに慣れていないので、私のチームはSubversionの代わりとして今それを試しています。

作業ディレクトリの他の変更をコミットせずに(または少なくとも他のリポジトリにプッシュしないで)単一のファイルを別のリポジトリにコミットしてプッシュするにはどうすればよいですか?

これは、データベースの移行で発生します。移行をソース管理にコミットして、データベースの移行に合わせてコードの変更を行っている間にDBAがそれを表示および編集できるようにします。変更はまだ準備ができていないため、すべてをプッシュする必要はありません。

Subversionでは、単に次のことを行います。

svn add my_migration.sql  
# commit only the migration, but not the other files I'm working on
svn commit -m "migration notes" my_mygration.sql

ローカルで作業を続けます。

これはMercurialでは機能しません。他のリポジトリにプッシュする場合、プルダウンしていない変更がある場合、プルダウンしてマージし、そのマージをコミットする必要があるためです。リポジトリ。マージ後のコミットでは、ファイルを省略できないため、ローカルリポジトリ内のすべてをコミットする必要があります。

私が理解できる最も簡単なことは、ファイルをローカルリポジトリにコミットし、ローカルリポジトリのクローンを作成し、実際のリポジトリから新しい変更をフェッチし、それらをマージしてそのマージをコミットし、変更をプッシュすることです。

hg add my_migration.sql 
hg commit -m "migration notes" my_migration.sql 
cd ..
hg clone project project-clone
cd project-clone
hg fetch http://hg/project
hg Push  http://hg/project

これは機能しますが、作業ディレクトリに既にあるファイルを無視するようにMercurialに指示し、マージを実行してファイルを送信するだけの簡単な方法が欠けているように感じます。 Mercurialのキューでこれができると思いますが、まだmqを完全に理解していません。

72
Ted Naleid

シェルブコマンドとアンシェルブコマンドを実装するMercurial機能があります。これにより、後から保存する変更をインタラクティブに指定できるようになります: Shelve

その後、hg shelveおよびhg unshelve変更を一時的に保存します。 「パッチハンク」レベルで作業して、棚に置くアイテムを選択できます。追加用にリストされたファイルを棚上げするようには見えず、変更済みのレポにすでにあるファイルのみが表示されました。

Mercurialには「拡張機能」として含まれており、hg configファイルで有効にする必要があるだけです。


本当に古いバージョンのMercurialのメモ(シェルフが含まれる前-これはもう必要ありません):

いくつかのグーグルで素晴らしいインストール手順が表示されなかったので、ここで私がそれを機能させるために使用したものを組み合わせました:

で入手:

hg clone http://freehg.org/u/tksoh/hgshelve/ hgshelve

(現在)プロジェクト内の唯一のファイルはhgshelve.pyファイルです。

〜/ .hgrcを変更してシェルブ拡張を追加し、リポジトリのクローンを作成した場所を指定します。

[extensions] 
hgshelve=/Users/ted/Documents/workspace/hgshelve/hgshelve.py
31
Josh Matthews

もともとこの質問を提起してからほぼ2年が経ちました。今は別の方法でやります(上記の質問の上のコメントで述べたように)。私が今やっていることは、代わりにローカルリポジトリの1つのファイルに変更をコミットすることです(hgレコード拡張子を使用してファイルの一部のみをコミットできます):

hg commit -m "commit message" filename

それからちょうど押し出してください。

hg Push

最初にマージする必要があるレポジトリに他の変更が加えられたために競合がある場合は、親リビジョンに更新します(それが何であるかわからない場合は「hg parent -r」で表示されます)、コミットしますそこに私の他の変更があるので、私は2つの頭を持っています。次に、元の単一ファイルコミットに戻り、変更をそのバージョンにプル/マージします。次に、変更をプッシュします

hg Push --rev .

単一のファイルとそのリビジョンのマージのみをプッシュアウトする。その後、ローカルで取得した2つのヘッドをマージできます。

この方法は、mqの要素と拒否されたハンクの可能性を取り除き、すべてをソース管理によって追跡し続けます。後でそれを望まない場合は、リビジョンを「hg strip」することもできます。

39
Ted Naleid

tl; dr:私の元の説明は複雑に見えますが、パッチキューの使用方法を完全に説明することを望みます。これは短いバージョンです:

$ hg qnew -m "migration notes" -f migration my_migration.sql
$ hg qnew -f working-code
# make some changes to your code
$ hg qrefresh # update the patch with the changes you just made
$ hg qfinish -a # turn all the applied patches into normal hg commits

Mercurial Queuesはこの種のことを簡単にし、変更セットのより複雑な操作を可能にします。学ぶ価値があります。

この状況では、まず変更をプルダウンする前に、現在のディレクトリにあるものを保存することをお勧めします。

# create a patch called migration containing your migration
$ hg qnew -m "migration notes" -f migration.patch my_migration.sql
$ hg qseries -v # the current state of the patch queue, A means applied
0 A migration.patch
$ hg qnew -f working-code.patch # put the rest of the code in a patch
$ hg qseries -v
0 A migration.patch
1 A working-code.patch

それでは、作業コードで追加の作業を行いましょう。明示的にするためにqseriesを実行し続けますが、パッチキューのメンタルモデルを構築したら、リストを見続ける必要はありません。

$ hg qtop # show the patch we're currently editing
working-code.patch
$ ...hack, hack, hack...
$ hg diff # show the changes that have not been incorporated into the patch
blah, blah
$ hg qrefresh # update the patch with the changes you just made
$ hg qdiff # show the top patch's diff

すべての作業がパッチキューに保存されるため、これらの変更を適用解除し、リモートの変更を取得した後に復元できます。通常、すべてのパッチを適用解除するには、hg qpop -a。パッチキューへの効果を示すために、一度に1つずつ削除します。

$ hg qpop # unapply the top patch, U means unapplied
$ hg qseries -v
0 A migration.patch
1 U working-code.patch
$ hg qtop
migration.patch
$ hg qpop
$ hg qseries -v
0 U migration.patch
1 U working-code.patch

この時点では、ディレクトリに変更がないかのようです。 hg fetch。これで、パッチキューの変更をプッシュし、競合がある場合はマージできます。これは、概念的にはgitのリベースに似ています。

$ hg qpush # put the first patch back on
$ hg qseries -v
0 A migration.patch
1 U working-code.patch
$ hg qfinish -a # turn all the applied patches into normal hg commits
$ hg qseries -v
0 U working-code.patch
$ hg out
migration.patch commit info... blah, blah
$ hg Push # Push out your changes

この時点で、他のローカルの変更を維持しながら、移行をプッシュしました。他の変更はキュー内のパッチにあります。パッチキューを使用して個人的な開発のほとんどを行い、変更をより適切に構成できるようにします。パッチキューを削除して通常のスタイルに戻したい場合は、変更をエクスポートし、「通常の」Mercurialで再インポートする必要があります。

$ hg qpush
$ hg qseries -v
0 A working-code.patch
$ hg export qtip > temp.diff
$ rm -r .hg/patches # get rid of mq from the repository entirely
$ hg import --no-commit temp.diff # apply the changes to the working directory
$ rm temp.diff

私は開発用のパッチキューに非常に夢中になっており、mqは最も優れた実装の1つです。複数の変更を同時に作成する機能により、コミットの集中度とクリーン度が向上します。慣れるまでしばらく時間がかかりますが、DVCSワークフローでは非常にうまくいきます。

10
Kobold

拡張機能に依存したくない場合のもう1つのオプションは、これらの種類の統合タスクにのみ使用するアップストリームリポジトリのクローンをローカルに保持することです。

この例では、変更を統合/アップストリームリポジトリにプル/マージし、リモートサーバーに直接プッシュすることができます。

3
Derek Slager

私が一般的に使用するのは、単一のファイルをコミットするために使用することです:

 hg commit -m "commit message" filename

後の場合、マージの競合があり、まだ変更をコミットする準備ができていません。次の手順に従ってください。

1)パッチファイルを作成します。

hg diff > changes.patch

2)パッチファイルを確認した後にのみ、未コミットのすべての変更を元に戻します。

hg revert --all

3)プル、更新、最新リビジョンへのマージ

hg pull -u
hg merge
hg commit -m "local merge"

4)パッチをインポートして戻し、変更を取得します。

hg import --no-commit changes.patch

変更を自動コミットする際に-no-commitフラグを使用することを忘れないでください。

2
Shweta

あなたが最も簡単だと言ったので、私はしばしばファイル全体をコミットするときでさえhg commit -i(--interactive)を使用します。 --interactiveを使用すると、コマンドラインにパス全体を入力するのではなく、必要なファイルを選択するだけで済みます。追加のボーナスとして、ファイル内のチャンクを選択的に含める/除外することもできます。

そして、hg Pushだけで、新しく作成されたコミットをプッシュします。

hg commit --interactiveの使用に関する詳細をこの回答に記載します。 https://stackoverflow.com/a/47931672/255961

1
studgeek