Subversion'daki geçici değişiklikleri geçici olarak kaldır (a la “git-stash”)


312

Bir Subversion deposunda depolanan yazılımları programlarken, genellikle bazı dosyaları değiştiririm, ardından ana çalışmam için bazı hazırlık değişiklikleri yapmak istediğimi fark ederim. Örneğin, yeni bir işlevsellik uygularken, bana yardımcı olabilecek bazı yeniden düzenlemeler görüyorum.

İlişkisiz iki değişikliği karıştırmamak için, bu gibi durumlarda değişiklikleri "saklamak", yani depo sürümüne geri dönmek, başka bazı değişiklikler yapmak, bunları yerine getirmek, sonra değişiklikleri "geri getirmek" istiyorum.

git-stash tam da bunu yapmanıza izin verir. Bunu Subversion ile doğrudan veya bazı eklenti veya komut dosyası ile yapmanın bir yolu var mı? Eclipse eklentileri de iyi olur.


6
sadece merak ediyorum, ama neden git-svn kullanmıyorsunuz?
cmcginty

3
İlgili bazı haberler: infoworld.com/d/application-development/… (alıntı: "Ayrıca yaklaşan Subversion 1.8 sürümünün, geliştiricinin yerel olarak değişiklik yapabileceği Git stash gibi özelliklerle Git yeteneklerine daha yakın olması gerektiğini de kaydetti. ve sonra bir kenara koy ve bir geliştirici çevrimdışı ve ana deposuna hamle yaparken kayıtları değişiklikleri tamamlandı çevrimdışı onaylatabilirsiniz, zaman geliştirici Reconnects ".
Sebastiaan van Broek den

1
Güncelleme (2012-04-26 itibariyle): Raflar artık ETA olmadan 1,9 için planlanıyor. Bu biraz zaman alabilir ...
sleske

10
Güncelleme (2012-11-17 itibariyle): Raflar şimdi 1.10 olarak planlanıyor. Belki her zaman <sonraki sürüm +1> için planlanmıştır? ;-)
sleske

3
Güncelleme (2015-03-23, 2 yıl ve yarım sonra): İyi haber şu ki Raflar hala 1.10 için planlanıyor. ETA: 2Ç 2015 (belirsiz) Sürüm 1.9.0 / 2017'de kötü haber var mı? (en iyi spekülatif) Sürüm 1.10.0 ( subversion.apache.org/roadmap.html )
ribamar

Yanıtlar:


69

Çalışma kopyamdaki bir görevden taahhüt edilmemiş değişiklikler olduğunda ve başka bir göreve geçmem gerektiğinde, iki şeyden birini yaparım:

  1. İkinci görev için yeni bir çalışma kopyasına bakın.

    veya

  2. Şube başlat:

    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
    

Bunu otomatikleştirmeye yardımcı olan bazı scriptlerim var.


65
bu, subversion sunucunuzda çok fazla
çöple sonuçlanacak

3
@knittl: Hayır, olmayacak. Ve daha da önemlisi: Öneriniz gibi değişikliklerin kaybolmasına neden olmaz. Bu ve gövde / aynı dalın başka bir kontrol kopyasına sahip olmak, bunu yapmanın tek iki güvenilir yoludur. Bundan rahatsızlık duyuyorsanız, başka bir kopyasına bakın ve paralel olarak üzerinde çalışın.
sbi

2
@knittl: şube, projenin varsayılan dalları veya etiketleri konumunun dışında olan göze çarpmayan bir yolda oluşturulabilir. Örneğin, bir ekip bu amaç için project\temp\<creationdate-reason>veya project\personal\<creationdate-reason>bu amaçla görev yapabilir.
rwong

12
Şubenin sunucuda oluşturulması hala talihsiz bir durumdur. Bu tür dallar çok fazla veriyi çoğaltmakla kalmaz, ama git gibi bir sistemin onsuz yaptığı birçok gereksiz referans oluştururlar.
thepeer

8
bu büyük bir depo için yararlı değildir. Bu kesinlikle çalışma ortamımda bir seçenek değil. Depomuzun daha küçük ve daha iyi organize edilmesini ve açıkçası, svn yerine bir git deposunu keşke olsa da, kodumuzun organizasyonumuzda nasıl düzenlendiğinin sınırlarıyla sınırlıyım.
AdrianVeidt

337

Bu blog gönderisi diff ve patch kullanımını önermektedir.

  • git stash yaklaşık olur svn diff > patch_name.patch; svn revert -R .
  • git stash apply olur patch -p0 < patch_name.patch

Bunun meta veri değişikliklerini saklamadığını veya (sanırım) dizin oluşturduğunu / sildiğini unutmayın. (Evet, svn bunları git'in aksine dizin içeriğinden ayrı olarak izler.)


13
Bu, stackoverflow.com/questions/1554278/… 'in yanlışlıkla bir kopyasıdır .
Walter Mundt

2
Ayrıca can sıkıcı olan ikili dosyaları içermiyor gibi görünüyor. En azından yamayı oluşturmak için TortoiseSVN kullanırken.
angularsen

1
stackoverflow.com/questions/159853/… bu konuda yardımcı olabilir.
Walter Mundt

6
Yama dosyasında olduklarından ve svn yaması bunları anladığı için, svn patch patch_name.patchyerine kullanırsanız, az ya da çok meta veriyi izleyebilirsiniz patch -p0.
mat

Bu, harici öğelerdeki değişiklikleri içermez.
congusbongus

182

Mevcut değişikliklerinizi svn diffbir yama dosyasına kaydedebilir, ardından çalışma kopyanızı geri alabilirsiniz:

svn diff > stash.patch
svn revert -R .

Hazırlık özelliğini uyguladıktan sonra, düzeltme ekini düzeltme eki yardımcı programıyla uygulayabilirsiniz:

patch < stash.patch

Diğerlerinin belirttiği gibi, bu svn:propertiesve ağaç işlemleri (dosya, dizin ekleme, kaldırma, yeniden adlandırma) ile çalışmaz .

İkili dosyalar da sorunlar verebilir, yama (veya TortoiseSVN bu durumda onları ele nasıl) bilmiyorum.


4
Bu muhtemelen kaldırılan / yeniden adlandırılmış dosyaları ile çok iyi çalışmıyor bence.
JesperE

7
"Yerine Yamalar Neden Kullanılmıyor?" Bunun neden kötü bir fikir olduğunu anlamak için svnbook.red-bean.com/en/1.5/… adresinde .
sbi

4
@sbi: Bunun bir aşağı oy için geçerli bir gerekçe olduğunu düşünmüyorum. Bu "kötü bir cevap" değil. Hepsi bu kadar mükemmel bir cevap değil. Bu kişinin önerisi için cezayı hak ettiğini düşünmüyorum. Onun yerine cevap vermemesini tercih eder misiniz? Cevabınız evet ise, evet, aşağı düşürmelisiniz. Aksi takdirde bu iyi niyetleri cezalandırır.
Sedat Kapanoglu

5
benim gibi başka birinin bunun en hafif çözüm gibi göründüğünü ve denemeye karar vermesi durumunda, patch -p0 <stash.patch kullanmak zorunda kaldım - aksi takdirde yama dosyalarını bulamamaktan şikayet etti
CupawnTae

4
Bu tavsiye, özellikle git arka planından geliyorsanız ve çeşitli nedenlerden dolayı SVN kullanmak zorunda kalırsanız yardımcı olur. İlk kez yama kullanıcıları için verilen tavsiyede küçük bir gelişme: $ patch --strip=0 < stash.patch Bu, yamayı uygularken yamanın size dosya adını sormamasını sağlayacaktır.
ksinkar

43

En kolay yol, aşağıdaki gibi geçici bir dal kullanmak olacaktır:

$ 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

Bu, daha düzenli olarak yapılırsa bir senaryoya konabilir (ve muhtemelen de konmalıdır).


2
Dosyaları sildiğinizde / eklediğinizde veya herhangi bir özelliği değiştirdiğinizde bile çalışmayan "çözümler" oylanırken neden bu oy kullanılır? Evet, bu ilk kez yaptığınızda yapılacak en kolay şey değildir, ancak paralel çalışmak için başka bir kopyanın kontrol edilmesinin yanı sıra, her durumda çalışan tek çözüm budur.
sbi

5
Repo kökü için ^ sözdiziminin güzel kullanımı (svn 1.6'dan beri). Deponuzda en üst düzeyde gövde / etiketler / dallar olduğunda iyi bir çözüm.
bendin

4
Tüm bu geçici dalları sunucuya koymaktan gerçekten hoşlanmıyorum. Sunucuyu karıştırmak yerine yerel olarak yapılması gerektiğini düşünüyorum (ve check-in sırasında posta oluşturursanız spurios check-in e-postaları üretmek). Yine de hatırlamaya değer bir seçenek.
sleske

3
@sleske: evet, geçici saklamanızı sunucuya veriyorsunuz, ancak şubenin kendisi siliniyor. Her neyse, bunun en hızlı ve en sağlam yol olduğunu düşünüyorum.
JesperE

5
@sleske: SVN dağıtılmış bir VCS değildir, bu nedenle her şeyin sunucuda olması gerekir. Tek yolu bu.
sbi

24

1.10.0'dan (2018-04-13) itibaren deneysel svn shelvekomutunuz var . ( TortoiseSVN komutu destekler ) Bir yamayı kaydetmek ve geri uygulamak bir yardımcıdan başka bir şey değildir, bu nedenle svn diff+ ile aynı sınırlamalara sahiptir patch(yani ikili dosyaları ve yeniden adlarını işleyemez). ( Düzenle : İkili destek bir sonraki sürüm 1.11.0'da geliyor gibi görünüyor )

Düzenleme ^ 2: 1.11.0 (2018-10-30'da yayınlandı) ile ikili dosyalar desteklenir . Yeniden adlandırılan dosyaların rafları desteklenmedi. 1.11'deki raflar, 1.10 tarafından oluşturulan raflarla uyumsuzdur.

Düzenleme ^ 3: 1.12.0 (2019-04-24'te yayınlandı) ile Kopyalama ve yeniden adlandırma desteklenir . 1.12 sürümündeki raflar, önceki sürümler tarafından oluşturulan raflarla uyumsuzdur.

Edit ^ 4: Raflarda 1.13.0 ve 1.14.0 ile değişiklik yapılmamıştır . Komutlar hala deneysel olarak işaretlenmiştir SVN_EXPERIMENTAL_COMMANDS=shelf3ve özelliği etkinleştirmek için tanımlamanız gerekir . Özellik şu anda açıklanmamış gibi görünüyor .

Tasarım notları geliştiricilerin Wiki'sinde bulunabilir .

$ 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

Bunu sadece svn ile yapmanın kolay bir yolunu bilmiyorum. Dürüst olmak gerekirse, git-svnbir svn çalışma kopyası olarak hareket eden bir git repo yapmak için kullanmanızı ve sadece git stashbununla kullanmanızı tavsiye ederim. Sadece yerini git pullile git svn rebaseve git pushile git svn dcommitve gerçekte git iş akışının% 90 tutabilir ve hala svn sunucusuna konuşacak.


Ancak stackoverflow.com/questions/1554278/… Yukarıdaki yorumlarda bahsettiğim bağlantı , sadece svn'de bir saklamak için pratik bir çözüm öneriyor.
VonC

Yeterince adil; Aslında, google beni şu anda bir blogda bu çözüme götürüyor. Bu soru soran için git-svn'in doğal bir çözüm olduğunu savunuyorum.
Walter Mundt

Git gitmediğinden çözümün dosya adlarını takip ettiğinden şüpheliyim.
NO_NAME

4

svn-stashGPL 3 altında kullanılabilen küçük bir Python 2 betiği vardır: https://github.com/frankcortes/svn-stash .

svn diff/patchBahsedilen çözümler gibi çalışır ve değişikliklerin diffs olarak bazı yerel dizine itilmesini ve patlatmasını sağlar. Ne yazık ki, stash'ler adlandırılamaz ve sadece sonuncusu patlayabilir (evet, evet, bu bir yığın, ancak böyle bir sınırlamanın gerçek bir nedeni yoktur.) Ama sonra, eksik özellikleri her zaman kaynak.

* İx için yazılmıştır, ancak her "/" yerine geçtikten sonra os.sepWindows altında da iyi çalışır.

Svn 1.7 veya daha üstünü kullanıyorsanız, değiştirmeniz gerekir is_a_current_stash(): if ".svn" in os.listdir(CURRENT_DIR):1.7 WC'lerde yalnızca bir üst düzey .svn alt dizini olduğundan , satırı kaldırın .


Benim için pencerelerin altında değil! :(
Antonio Petricca


3

diğer bir seçenek, mevcut ödünç alma işleminizi yeni bir dizine kopyalayıp tüm değişikliklerinizi geri almaktır. bu şekilde sunucunuzda geçici bir şube oluşturma zahmetinden kurtulacaksınız - sonuçta herkesin görmemesi ve sık sık yapılabileceği yerel bir işlemdir.

düzeltmenizi yaptıktan sonra ana çalışma kopyasını güncelleyebilir ve "depolama alanı" silebilir


Not: Bu aslında ikinci bir çalışma kopyasını kontrol etmekle aynıdır - sadece ödeme yapmadan :-).
sleske

6
@sleske: evet, yeni bir ödeme için gerekli büyük miktarda bant genişliği olmadan
knittl

Beğen ya da beğenme, "git stash" davranışını daha yakından yansıtan cevaptır. Bir şube oluşturmak iyidir, ancak daha çok TFS raflarıyla ilgilidir.
Charles Roberto Canato

1

Ben de bu özelliği istedim. Şu anda TortoiseSVN kullanıyorum.

Ağacı dışa aktarma, depoya geri dönme ve değişikliklerimi yapma ve taahhüt etme dışında daha hızlı bir çözüm bulamadım, daha sonra Dışa Aktarma Ötesinde gibi bir araç kullanarak dışa aktarılan ağaçtaki değişiklikleri kaynak kontrollü dizine karşılaştırın.

Veya başka bir çözüm, HEAD'den başka bir dizine dallanmak, değişikliklerinizi ve taahhüdünüzü yapmak olabilir. Bunları diğer çalışan kopyanızla birleştirmeye hazır olduğunuzda, bir güncelleme yapın ve değişikliklerinizi birleştirin.


1

Ben her zaman "trunk_clean" dediğim ikinci bir ödeme tutmak. Ne yaptığımla ilgili hızlı ve izole bir değişiklik yapmam gerektiğinde bunun yerine ödeme yapmayı taahhüt ederim.


0

Yukarıdaki dallanma ve yama fikirleri harika, ama benim için iyi çalışmıyorlar. Görsel bir fark aracı kullanıyorum, bu yüzden çalıştırmak git diffmetin tabanlı yamalar üretmiyor. Oluşturma sistemimiz her dal oluşturulduğunda yeni bir ortam oluşturur, bu nedenle geçici "saklamak" dalları oluşturmak dağınık olur.

Bunun yerine, bir dosyayı "raf" dizinine kopyalayan, zaman damgası ekleyen ve değişikliği geri alan küçük bir kabuk komut dosyası yazdım . Yukarıdaki çözümler kadar sağlam değil, aynı zamanda karşılaştığım bazı tuzaklardan da kaçınıyor.


0

Walter'ın cevabına dayanarak bashrc dosyamda aşağıdaki takma adları oluşturdum:

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'

Bu takma adların kullanımı ve hatırlanması çok daha kolaydır.

Kullanımı:

saklamak için svn.stash ve saklamak için svn.stash.apply uygulayın.


0

Benim pratiğimde, Subversion depomun dizininde git initbir Git deposu oluşturmak için kullanıyorum trunkve sonra *.gitSuctions yok sayma kalıplarını ekliyorum.

Bazı dosyaları değiştirdikten sonra, Subversion ana hattıyla çalışmaya devam etmek istersem, sadece git stashişimi saklamak için kullanıyorum . Subversion deposuna geçtikten sonra git stash popdeğişikliklerimi geri yüklemek için kullanıyorum .


2
Bu aslında iyi bir çözüm! Diğer birçok çözüm, sorunu çözmek için 3. taraf araçlarını kullanır; Bu, Git'i üçüncü taraf bir araç olarak kullanır. Bunun birkaç avantajı vardır: 1) Git çok genel ve güçlü. 2) Birçok kişinin Git'i zaten yüklüdür.
Lii

Git komutunu da yapmazsanız bunun nasıl çalıştığını merak ediyorum.
B2K

0

kullanın:

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

Geçerli konumdan ve geçerli revizyondan bir şube oluşturacak ve daha sonra o şubeye geçiş yapmadan çalışma kopyasındaki değişiklikleri gerçekleştirecektir.

kullanım: SRC'yi kopyala [@REV] ... DST

SRC ve DST'nin her biri çalışan bir kopya (WC) yolu veya URL olabilir:

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

Çalışan kopyadaki değişikliklerin otomatik olarak geri alınmayacağını unutmayın ( cpyalnızca CoPying) yeni bir dalda değişiklikleri olduğunu) ve bunları manuel olarak geri döndürmeniz gerektiğini unutmayın.

Değişiklikleri geri yüklemek için, yeni oluşturulan daldaki değişiklikleri çalışma kopyanızla birleştirebilirsiniz.

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

--ignore-ancestry çalışma kopyasındaki birleştirme bilgilerini güncellememek için kullanılır.

kullanın:

svn ls -v ^/trash-stash/

saklamak için ne var görmek için. Taahhüt edilen revizyonlar da yazdırılır.

Artık depolamaya ihtiyacınız yoksa çalıştırın:

svn rm ^/trash-stash/my-stash

Bu çözüm yamayı kullanmaktan daha iyidir, çünkü çalışma kopyasında veya mevcut dalda yeni değişiklikler saklanan değişikliklerle çakışırsa, svn araçlarını kullanarak çakışmaları çözebilirsiniz, oysa patchbazı durumlarda yama yanlış olur.


-1

Subversion stashözelliği mükemmel bir şekilde desteklemediğinden ,
sadece böyle bir yol yapıyorum.

Yer Developmentve Production(release)ayrı bir yol projesi.

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

Projeniz için herhangi bir yeni özelliği geliştirme yolunda çalıştırabilirsiniz
ve sadece anlamlı bir ilerleme kaydedersiniz veya ahır için bir şey yayınlanmalıdır.

Üretim için serbest bırakmanız gerektiğinde, üretim projesini açın, svn'yi güncelleyin ve serbest bırakmak için bir şeyler yapın (inşa edin, dışa aktarın ... vb.).

Bunun biraz zahmetli hale geldiğini biliyorum, ancak ilerlemeyi bırakmak sık sık gerçekleşmiyor (benim için değil, ama bazı projelerin yaptığını biliyorum) ilerlemeyi geliştirmek için karşılaştır, bu şekilde benim için uygun.

Proje ekibi üyeleri kullandığından svn'yi belirli projeler için kullanıyorum, bu yüzden takip etmeliyim.
En iyi çözüm, gitmükemmel bir sürüm kontrol sistemine sahip ve daha iyi kullanmaktır svn.


Ne yaptığınızı tam olarak bilmiyoruz (bahsettiğiniz dizinlerde hangi sürüm kontrol edildi?), Ancak en çok oy alan cevabın bir kopyası gibi görünüyor ("Yeni bir çalışma kopyasına bakın").
sleske

@sleske Üzgünüm, dava detaylarınızı okumadım. Benim durumumda, sadece devve prod2 duruma ihtiyacım var . Tamamen yeni işlevsellik geliştirmek svn ile karmaşık olacaktır. Svn dünyasında davanızı çözmek için net bir yöntem olup olmadığından emin değilim.
wonsuc
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.