Subversionのコミットされていない変更を一時的に片付けます(「git-stash」のように)


312

Subversionリポジトリに格納されたソフトウェアをプログラミングしているときに、いくつかのファイルを変更することがよくあります。その後、メインの作業のためにいくつかの準備的な変更を行いたいことに気づきます。たとえば、新しい機能を実装しているときに、いくつかのリファクタリングが役立ちます。

2つの無関係な変更を混合しないように、これらの場合、変更を「格納」します。つまり、リポジトリバージョンに戻し、他の変更をいくつか行い、これらをコミットしてから、変更を「フェッチバック」します。

git-stashはまさにそれを可能にします。直接、またはプラグインやスクリプトを使用して、Subversionでこれを行う方法はありますか?Eclipseプラグインも問題ありません。


6
好奇心旺盛ですが、なぜgit-svnを使わないのですか?
cmcginty 2010

3
いくつかの関連ニュース:infoworld.com/d/application-development/…(引用: "また、開発者はローカルで変更を加えることができるGit stashのような機能を備えた、次のSubversion 1.8リリースがGitの機能により近づくと述べています。そして、それらを脇に置き、オフラインコミット。開発者がオフラインのときに完了した変更を記録し、開発者が再接続したときにマスターリポジトリに移動します。」
Sebastiaan van den Broek

1
更新(2012年4月26日現在):ETAなしで棚付けが1.9にスケジュールされるようになりました。しばらく時間がかかるかもしれません...
sleske 2012

10
更新(2012年11月17日現在):棚付けは1.10に予定されています。多分それは常に<次のリリース+1>に予定されていますか?;-)
sleske 2012年

3
更新(2015年3月23日現在、2年半後):朗報は、シェルビングがまだ1.10に予定されていることです。悪いニュースはETAです:2015年第2四半期(暫定)リリース1.9.0 / 2017?(せいぜい投機的)リリース1.10.0(subversion.apache.org/roadmap.html
ribamar 2015年

回答:


69

作業コピーの1つのタスクからコミットされていない変更があり、別のタスクに切り替える必要がある場合は、次の2つのいずれかを行います。

  1. 2番目のタスクの新しい作業コピーをチェックアウトします。

    または

  2. ブランチを開始します。

    workingcopy$ svn copy CURRENT_URL_OF_WORKING_COPY SOME_BRANCH
    workingcopy$ svn switch SOME_BRANCH
    workingcopy$ svn commit -m "work in progress"
    workingcoyp$ svn switch WHATEVER_I_WAS_WORKING_ON_BEFORE
    

これを自動化するのに役立つスクリプトがあります。


65
これにより、Subversionサーバーに大量のゴミが発生します
knittl '12年

3
@knittl:いいえ、ありません。さらに重要なのは、提案のように変更が失われることはないということです。これと、trunk / sameブランチの別のチェックアウト済みコピーがあることは、これを実行するための信頼できる2つの方法です。これが気に入らない場合は、別のコピーをチェックアウトして、並行して作業してください。
sbi 2009年

2
@knittl:ブランチは、プロジェクトのデフォルトのブランチまたはタグの場所の外にある目立たないパスに作成できます。たとえば、チームはこの目的のために、project\temp\<creationdate-reason>またはproject\personal\<creationdate-reason>この目的で指定できます。
2010年

12
ブランチをサーバー上に作成する必要があることは、まだ残念です。このようなブランチが大量のデータを複製するのではなく、gitのようなシステムでは不要な多くの不要な参照を作成します。
ピア

8
これは大きなリポジトリでは役に立ちません。これは私の職場環境では絶対に選択肢ではありません。そして、私は私たちのリポジトリが小さく、よりよく整理されていて、率直に言って、svnではなくgitリポジトリであることを望みますが、私は組織内でのコードの編成方法の制限に制限されています。
AdrianVeidt 2014年

337

このブログ投稿では、diffとpatchの使用についてアドバイスしています。

  • git stash ほぼになる svn diff > patch_name.patch; svn revert -R .
  • git stash apply なる patch -p0 < patch_name.patch

これはメタデータの変更を隠したり、ディレクトリを作成/削除したりしないことに注意してください。(はい、svnはgitとは異なり、ディレクトリの内容とは別に追跡します。)


13
これは、stackoverflow.com / questions / 1554278 /…の誤った複製です-そこに賛成票を送信してください。
Walter Mundt、2010

2
また、バイナリファイルが含まれていないようで、煩わしいです。少なくともTortoiseSVNを使用してパッチを生成する場合。
angularsen 2013


6
svn patch patch_name.patch代わりにを使用するとpatch -p0、メタデータを追跡することができます。これは、メタデータがパッチファイルにあり、svn patchがそれらを理解するためです。
2014

これには、外観の変更は含まれません。
congusbongus 14

182

現在の変更をsvn diffパッチファイルに保存してから、作業コピーを元に戻すことができます。

svn diff > stash.patch
svn revert -R .

準備機能を実装したら、パッチユーティリティを使用してパッチを適用できます。

patch < stash.patch

他の人が指摘したように、これはsvn:propertiesツリー操作(ファイルとディレクトリの追加、削除、名前変更)では機能しません。

バイナリファイルでも問題が発生する可能性があります。パッチ(この場合はTortoiseSVNが処理する方法)がわかりません。


4
これはおそらく、削除/名前変更されたファイルではあまりうまく機能しないと思います。
JesperE 2009年

7
「代わりにパッチを使用しない理由」というボックスを参照してください。svnbook.red-bean.com/en/1.5/…で、これが悪い考えである理由を理解してください
sbi 2009年

4
@sbi:それは反対投票の正当な理由だとは思わない。「悪い答え」ではありません。完全な答えではありません。この人は彼の提案に対して罰するに値するとは思わない。代わりに彼に答えない方がいいですか。はいの場合、はい、あなたは反対票を投じるべきです。それ以外の場合、これは善意を罰します。
セダットカパノグル2009年

5
それ以外の場合は、誰に、私のような、最軽量のソリューションのように、このルックスを考えて、それを試すことにしました、私はパッチ-p0 <stash.patchを使用していた-それ以外の場合は、程度のパッチにファイルを見つけることができない不満を
CupawnTae

4
このアドバイスは、gitのバックグラウンドから来ていて、さまざまな理由でSVNを使用せざるを得ない場合に特に役立ちます。パッチを初めて使用するユーザー向けに既に提供されているアドバイスの小さな改善: $ patch --strip=0 < stash.patch これにより、パッチを適用するときに、パッチがファイル名を尋ねないようになります。
ksinkar 2014

43

最も簡単な方法は、次のように一時的なブランチを使用することです。

$ svn copy ^/trunk ^/branches/tempbranch
$ svn switch ^/branches/tempbranch
$ svn commit -m "Stashed"
$ svn switch ^/trunk
$ ... hack away in trunk ...
$ svn commit -m "..."
$ svn merge ^/branches/tempbranch .
$ svn rm ^/branches/tempbranch
$ ... continue hacking

これは、より定期的に実行する場合、スクリプトに含めることができます(おそらくそうする必要があります)。


2
ファイルが削除または追加された場合、またはプロパティが変更された場合に機能しない「ソリューション」が投票されたのに、なぜこれが投票されたのですか?はい、これは初めて行うときに最も簡単なことではありませんが、別のコピーをチェックアウトして並行して機能させる以外に、これはすべての場合に機能する唯一のソリューションです。
sbi 2009年

5
リポジトリのルートに^構文を使用する(svn 1.6以降)。リポジトリに最上位にトランク/タグ/ブランチがある場合の良い解決策。
2009年

4
これらの一時的なブランチをすべてサーバーに配置するのはあまり好きではありません。サーバーを雑然とさせるのではなく、ローカルで行う必要があると思います(チェックイン時にメールを生成する場合は、spuriosチェックインメールを生成します)。それでも、覚えておく価値のあるオプションです。
sleske

3
@sleske:はい、一時的な隠し場所をサーバーにコミットしていますが、ブランチ自体は削除されています。とにかく、これが最も速く、最も堅牢な方法だと思います。
JesperE 2009年

5
@sleske:SVNは分散型VCSではないため、すべてがサーバー上にある必要があります。仕方ないよ。
sbi

24

1.10.0(2018-04-13)以降、実験的なsvn shelveコマンドがあります。(TortoiseSVNはこのコマンドをサポートしています)パッチを保存して適用し直すのはヘルパーに過ぎないため、svn diff+ と同じ制限がありますpatch(つまり、バイナリファイルを処理して名前を変更することはできません)。(編集バイナリサポートは次のバージョン1.11.0で提供されるようです

Edit ^ 2: 1.11.0(2018年10月30日リリース)では、バイナリファイルがサポートされています。名前が変更されたファイルのシェルビングはサポートされませんでした。1.11のシェルビングは、1.10で作成されたシェルフと互換性がありません。

Edit ^ 3: 1.12.0(2019年4月24日リリース)では、コピーと名前の変更がサポートされています。1.12のシェルビングは、以前のバージョンで作成されたシェルフと互換性がありません。

編集^ 4:1.13.01.14.0 では、シェルビングに関する変更はありません。コマンドはまだ実験的としてマークされておりSVN_EXPERIMENTAL_COMMANDS=shelf3、機能を有効にするために定義する必要があります。機能は現在トリアージされていないようです

デザインノートは開発者のWikiにあります。

$ svn x-shelve --help
x-shelve: Move local changes onto a shelf.
usage: x-shelve [--keep-local] SHELF [PATH...]

  Save the local changes in the given PATHs to a new or existing SHELF.
  Revert those changes from the WC unless '--keep-local' is given.
  The shelf's log message can be set with -m, -F, etc.

  'svn shelve --keep-local' is the same as 'svn shelf-save'.

  The kinds of change you can shelve are committable changes to files and
  properties, except the following kinds which are not yet supported:
     * copies and moves
     * mkdir and rmdir
  Uncommittable states such as conflicts, unversioned and missing cannot
  be shelved.

  To bring back shelved changes, use 'svn unshelve SHELF'.

  Shelves are currently stored under <WC>/.svn/experimental/shelves/ .
  (In Subversion 1.10, shelves were stored under <WC>/.svn/shelves/ as
  patch files. To recover a shelf created by 1.10, either use a 1.10
  client to find and unshelve it, or find the patch file and use any
  1.10 or later 'svn patch' to apply it.)

  The shelving feature is EXPERIMENTAL. This command is likely to change
  in the next release, and there is no promise of backward compatibility.

Valid options:
  -q [--quiet]             : print nothing, or only summary information
  --dry-run                : try operation but make no changes
  --keep-local             : keep path in working copy

(...)

$ svn x-unshelve --help
x-unshelve: Copy shelved changes back into the WC.
usage: x-unshelve [--drop] [SHELF [VERSION]]

  Apply the changes stored in SHELF to the working copy.
  SHELF defaults to the newest shelf.

  Apply the newest version of the shelf, by default. If VERSION is
  specified, apply that version and discard all versions newer than that.
  In any case, retain the unshelved version and versions older than that
  (unless --drop is specified).

  With --drop, delete the entire shelf (like 'svn shelf-drop') after
  successfully unshelving with no conflicts.

  The working files involved should be in a clean, unmodified state
  before using this command. To roll back to an older version of the
  shelf, first ensure any current working changes are removed, such as
  by shelving or reverting them, and then unshelve the desired version.

  Unshelve normally refuses to apply any changes if any path involved is
  already modified (or has any other abnormal status) in the WC. With
  --force, it does not check and may error out and/or produce partial or
  unexpected results.

  The shelving feature is EXPERIMENTAL. This command is likely to change
  in the next release, and there is no promise of backward compatibility.

Valid options:
  --drop                   : drop shelf after successful unshelve
(...)

$ svn help | grep x-
 x-shelf-diff
 x-shelf-drop
 x-shelf-list (x-shelves)
 x-shelf-list-by-paths
 x-shelf-log
 x-shelf-save
 x-shelve
 x-unshelve

9

私はsvnだけでそれを行う簡単な方法を知りません。正直なところ、私はgit-svnsvn作業コピーとして機能するgitリポジトリを作成するためにを使用し、それを使用することをお勧めしgit stashます。ただ、交換するgit pullgit svn rebasegit pushgit svn dcommit、あなたが実際にあなたのGitのワークフローの90%を維持することができ、まだSVNサーバーに話をすること。


しかし、リンクstackoverflow.com/questions/1554278/…上のコメントで言及したように、svnでのみstashを実行するための実用的なソリューションを提案しています。
VonC、2010

けっこうだ; 実際、グーグルがブログでその解決策を教えてくれました。この質問者にとって、git-svnは自然な解決策であると私はまだ主張しています。
Walter Mundt、2010

gitはそうではないので、解決策がファイルの名前変更に従うかどうかは疑問です。
NO_NAME 2015

4

svn-stashGPL 3:https : //github.com/frankcortes/svn-stashで利用可能なと呼ばれる小さなPython 2スクリプトがあります

これは、svn diff/patch前述のソリューションと同様に機能し、変更をローカルディレクトリへの差分としてプッシュおよびポップします。残念ながら、スタッシュに名前を付けることはできず、最後のスタッシュのみをポップできます(そうですね、それはスタックですが、そのような制限の本当の理由はありません)。しかし、不足している機能をいつでもソース。

これは* ix用に書かれていますが、「/」をすべて置き換えた後、os.sepWindowsでもうまく機能します。

svn 1.7以降を使用する場合は、変更する必要があります。1.7WCには最上位の.svnサブディレクトリが1つしかないis_a_current_stash()ため、行を削除しif ".svn" in os.listdir(CURRENT_DIR):ます。


私は窓の下ではそれをしません!:(
アントニオペトリカ

4

Intellij IDEA-Shelve Changesを使用して簡単に行うことができます


この方法では処理できないmetadata changesdirectory creates/deletes?正確には何git stashが好きですか?
wonsuc

3

別のオプションは、現在のチェックアウトを新しいディレクトリにコピーして、すべての変更を元に戻すことです。このようにすれば、サーバーに一時的なブランチを作成する手間を省くことができます。すべての隠蔽がローカル操作であるため、誰もが見る必要はなく、頻繁に実行できるわけではありません。

修正プログラムをコミットした後、メインの作業用コピーを更新して、「隠し場所」を削除できます


注:これは基本的に、2番目の作業コピーをチェックアウトするのと同じです-チェックアウトがない場合のみです:-)。
sleske

6
@sleske:はい、新しいチェックアウトに必要な大量の帯域幅なし
knittl

好むと好まざるとにかかわらず、これは「git stash」の動作をより厳密に反映する答えです。ブランチの作成は便利ですが、TFSシェルフに関連しています。
Charles Roberto Canato 2015年

1

この機能も欲しかった。私は現在TortoiseSVNを使用しています。

ツリーをエクスポートし、リポジトリに戻って変更を加えてコミットし、Beyond Compareなどのツールを使用して、エクスポートしたツリーからの変更をソース管理ディレクトリに戻す以外に、ハードファストソリューションは見つかりませんでした。

または、別の解決策として、HEADから別のディレクトリに分岐し、変更を加えてコミットすることもできます。それらを他の作業コピーにマージする準備ができたら、更新を行い、変更をマージします。


1

私は常に「trunk_clean」と呼ばれる2番目のチェックアウトを保持します。私がやっていることに関連して、迅速で孤立した変更を行う必要があるときはいつでも、代わりにそのチェックアウトをコミットします。


0

上記のブランチとパッチのアイデアは素晴らしいですが、私にはうまくいきません。私は視覚的な差分ツールを使用しているため、実行git diffしてもテキストベースのパッチは生成されません。ビルドシステムは、ブランチが作成されるたびに新しい環境を起動するため、一時的な「スタッシュ」ブランチの作成は面倒になります。

代わりに、ファイルを「シェルフ」ディレクトリにコピーし、タイムスタンプを追加して、変更を元に戻す小さなシェルスクリプトを作成しました。これは上記のソリューションほど堅牢ではありませんが、私が遭遇したいくつかの落とし穴を回避します。


0

Walterの回答に基づいて、bashrcファイルに次のエイリアスを作成しました。

alias svn.stash='read -p "saving local changes in raq.patch. Existing stash in raq.patch will be overwritten. Continue?[y/N]" && [[ $REPLY =~ ^[yY] ]] && rm -f raq.patch && svn diff > raq.patch && svn revert -R .'
alias svn.stash.apply='patch -p0 < raq.patch; rm -f raq.patch'

これらのエイリアスは使いやすく覚えやすいです。

使用法:

svn.stashは変更を隠し、svn.stash.applyはstashを適用します。


0

私の練習では、Subversionリポジトリーのディレクトリーにgit initGitリポジトリーを作成するために使用してから、Suctions ignoreパターンtrunkに追加*.gitします。

一部のファイルを変更した後、Subversionメインラインで作業を続けたい場合は、作業git stashを隠しておくだけです。Subversionリポジトリーにコミットした後、私git stash popは変更を復元するために使用します。


2
これは実際には良い解決策です!他の多くのソリューションでは、サードパーティのツールを使用して問題を解決しています。これはサードパーティのツールとしてGitを使用しています。これにはいくつかの利点があります:1)Gitは非常に一般的で強力です。2)多くの人がすでにGitをインストールしています。
Lii

git commitも行わない場合、これがどのように機能するか知りたいです。
B2K 2018年

0

使用する:

svn cp --parents . ^/trash-stash/my-stash

現在の場所と現在のリビジョンからブランチを作成し、作業コピーの変更を切り替えずにそのブランチにコミットします。

使用法:SRC [@REV]をコピー... DST

SRCとDSTは、それぞれ作業コピー(WC)パスまたはURLのいずれかです。

WC  -> URL:  immediately commit a copy of WC to URL

作業コピーの変更を自動的に(元に戻されないことに注意してくださいcpだけさ変更を新しいブランチにです)、手動で元に戻す必要があることに注意してください。

変更を復元するには、新しく作成されたブランチからの変更を作業コピーにマージするだけです。

svn merge --ignore-ancestry ^/trash-stash/my-stash -c <commited revision>

--ignore-ancestry 作業コピーのマージ情報を更新しないために使用されます。

使用する:

svn ls -v ^/trash-stash/

あなたが隠し場所にあるものを見るために。コミットされたリビジョンも印刷されます。

stashが不要になった場合は、次のコマンドを実行してください。

svn rm ^/trash-stash/my-stash

この解決策は、パッチを使用するよりも優れています。作業コピーまたは現在のブランチでの新しい変更がstashの変更と競合するpatch場合、svnの手段を使用して競合を解決できますが、場合によっては失敗するか、パッチを誤って適用することさえあります。


-1

Subversionはstash機能を完全にはサポートしていないため、
このように手動で実行します。

別のパスに配置DevelopmentしてProduction(release)投影します。

source\code\MyApp         -- Development
release\MyApp(release)    -- Production(release)

開発パスでは、プロジェクトの新機能を使用できます。
意味のある進捗のみをコミットするか、安定版にリリースする必要があります。

プロダクション用にリリースする必要がある場合は、プロダクションプロジェクトを開き、svnを更新して、リリースするための作業(ビルド、エクスポートなど)を行います。

これが少し面倒になることは知っていますが、進捗状況をリリースすることは頻繁には起こりません(私にとってはそうではありませんが、いくつかのプロジェクトはそうです)進捗状況を開発と比較すると、この方法が適しています。

プロジェクトチームのメンバーがsvnを使用しているため、特定のプロジェクトにsvnを使用しているので、フォローする必要があります。
最良の解決策はgit、完璧なバージョン管理システムを備えたを使用することですsvn


あなたが何をしているのかははっきりしていませんが(あなたが言及しているディレクトリでどのバージョンがチェックアウトされていますか?)、それはトップ投票の回答(「新しい作業コピーをチェックアウトする」)の複製のようです。
sleske

@sleske申し訳ありませんが、ケースの詳細を読みませんでした。私の場合、私は必要devprod、2つの状況。完全に新しい機能を開発することは、svnでは複雑になります。SVNの世界であなたのケースを解決する明確な方法があるかどうかはわかりません。
wonsuc
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.