Git şubelerini nasıl arşivleyebilirim?


305

Git depomda artık aktif geliştirme aşamasında olmayan bazı eski şubelerim var. Dalları, çalışırken varsayılan olarak görünmemeleri için arşivlemek istiyorum git branch -l -r. Onları silmek istemiyorum çünkü tarihi saklamak istiyorum. Bunu nasıl yapabilirim?

Refs / head'ların dışında ref oluşturmanın mümkün olduğunu biliyorum. Örneğin refs/archive/old_branch,. Bunu yapmanın herhangi bir sonucu var mı?


Git-rm sadece dizinden onları kaldırır deposundan değil silme kaynaklar yapar kernel.org/pub/software/scm/git/docs/git-rm.html Kolayca kullanarak bu kaynakları geri yükleyebilirsinizgit checkout [rev] file
Sane Dana

1
Bildiğim kadarıyla hayır. Attic/<branchname>Yine de dalları arşivlemek için hafif etiketler kullanıyorum .
Jakub Narębski

Etiketler hızlı ve güvenli ve akıllıca bir seçimdir.
kch

Yanıtlar:


401

Bunu yapmanın doğru yolunun şubeyi etiketlemek olduğuna inanıyorum. Şubeyi etiketledikten sonra silerseniz, şubeyi etkili bir şekilde saklamış olursunuz, ancak şube listenizi karıştırmaz.

Şubeye geri dönmeniz gerekiyorsa, etikete bakın. Şubeyi etkin bir şekilde etiketinden geri yükler.

Şubeyi arşivlemek ve silmek için:

git tag archive/<branchname> <branchname>
git branch -d <branchname>

Şubeyi bir süre sonra geri yüklemek için:

git checkout -b <branchname> archive/<branchname>

Şubenin geçmişi, tam olarak etiketlediğinizde olduğu gibi korunacaktır.


11
Ben bir Git acemi, ama bunu denerken, şube geri yükleme için uygun komut olduğunu düşünüyorum:git checkout -b <branchname> archive/<branchname>
Steve

6
Bu durumda bir nesne etiketi kullanmamanın bir nedeni var mı? Şubeyi kimin ne zaman arşivlediğini görebilme.
Grégory Joseph

7
@ GrégoryJoseph: Bu, "açıklamalı etiket" olarak adlandırılıyor. Ve evet, bunu kullanmak çok mantıklı olabilir.
onnodb

22
küçük bir not, muhtemelen branch -Dbu şekilde arşivlerseniz tam olarak birleştirilmemesi muhtemeldir
Arkadiy Kukarkin

5
Çok hoş. İşte açıklamalar ile eksiksiz bir öğretici.
guyaloni

123

Jeremy'nin cevabı prensipte doğrudur, ancak IMHO'nun belirttiği komutlar doğru değildir.

Şube çıkış yapmak zorunda kalmadan bir dalı bir etikete nasıl arşivleyeceğiniz aşağıda açıklanmıştır (ve bu nedenle, o dalı silmeden önce başka bir şubeye ödeme yapmak zorunda kalmadan):

> git tag archive/<branchname> <branchname>
> git branch -D <branchname>

Şube nasıl geri yüklenir:

> git checkout -b <branchname> archive/<branchname>

18
Sanırım henüz yeterli puanınız olmadı ama mevcut cevabı düzenlemek için yaptığınız zaman daha iyi olurdu - +1 yine de :)
jkp

5
@jkp, diğer kullanıcıların kodlarını ve komutlarını düzenlemek genellikle kaşlarını çatır çünkü git komutundaki küçük değişiklikler büyük ölçüde farklı şeyler yapabilir ve orijinal yazarın neden bir şeyi yaptıkları gibi yazdığını anlamayabilirsiniz. kendi cevabınızı vermek veya yorum bırakmak daha iyidir.
Dan Bechard

Ya da çok farklı şeylerden daha kötüsü, komutlarda veya kodda yapılan ince bir değişiklik, anlaşılması gerçekten zor olabilen oldukça farklı sonuçlara yol açabilir. potansiyel olarak farklı sonuçlara atıfta bulunan bir karşı iddia ile (Bu karşı iddialar oldukça yaygındır)
Nicholas Pipitone

22

Evet, kullanarak standart olmayan bazı öneklerle bir ref oluşturabilirsiniz git update-ref. Örneğin

  • Şubeyi arşivle: git update-ref refs/archive/old-topic topic && git branch -D topic
  • Şubeyi geri yükleyin (gerekirse): git branch topic refs/archive/old-topic

Standart olmayan öneki (burada refs/archive) olan referanslar normalde görünmez git branch, git logne de git tag. Yine de bunları listeleyebilirsiniz git for-each-ref.

Aşağıdaki takma adları kullanıyorum:

[alias]
    add-archive = "!git update-ref refs/archive/$(date '+%Y%m%d-%s')"
    list-archive = for-each-ref --sort=-authordate --format='%(refname) %(objectname:short) %(contents:subject)' refs/archive/
    rem = !git add-archive
    lsrem = !git list-archive

Ayrıca, arşivlenen dalları otomatik olarak (veya tek çekim için) itmek gibi uzaktan kumandaları yapılandırmak isteyebilirsiniz .push = +refs/archive/*:refs/archive/*git push origin refs/archive/*:refs/archive/*

Başka bir yol da şubeyi silmeden önce SHA1'i bir yere yazmaktır, ancak sınırlamaları vardır. Herhangi bir ref'siz taahhütler , manuel olarak bırakılmaksızın 3 ay sonra (veya reflog olmadan birkaç hafta sonra) GC'd olacaktırgit gc --prune . Ref'lerin işaret ettiği taahhütler GC'den güvenlidir.

Düzenleme: @ap tarafından aynı fikrin perl uygulaması bulundu :git-attic

Edit ^ 2: Gitster'ın da aynı tekniği kullandığı bir blog yazısı bulundu .


3
Mükemmel, bu konudaki herkes dışında, aslında soruyu cevapladınız.
tzrlk

20

Steve'in cevabını uzaktan kumandadaki değişiklikleri yansıtacak şekilde genişleterek yaptım

 git tag archive/<branchname> <branchname>
 git branch -D <branchname>
 git branch -d -r origin/<branchname>
 git push --tags
 git push origin :<branchname>

Uzaktan kumandadan geri yüklemek için bu soruya bakın .


18

Şubeleri başka bir depoda arşivleyebilirsiniz. O kadar zarif değil, ama bunun uygun bir alternatif olduğunu söyleyebilirim.

git push git://yourthing.com/myproject-archive-branches.git yourbranch
git branch -d yourbranch

4
git-bundleAyrı depo yerine oluşturabilirsiniz .
Jakub Narębski

9

İşte bunun için bir takma ad:

arc    = "! f() { git tag archive/$1 $1 && git branch -D $1;}; f"

Bu şekilde ekleyin:

git config --global alias.arc '! f() { git tag archive/$1 $1 && git branch -D $1;}; f'

git archiveZaten bir komut olduğunu unutmayın, bu yüzden archivetakma ad olarak kullanamazsınız .

Ayrıca 'arşivlenmiş' dalların listesini görüntülemek için takma ad tanımlayabilirsiniz:

arcl   = "! f() { git tag | grep '^archive/';}; f"

takma ad ekleme hakkında


3
Git'in daha yeni sürümleriyle ( burada önerildiği gibi ), bu takma ad tamamlanır:!git tag archive/$1 $1 && git branch -D
eksik

5

Arşivlenmiş dalları gizlemek için aşağıdaki takma adları kullanıyorum:

[alias]
    br = branch --no-merge master # show only branches not merged into master
    bra = branch                  # show all branches

Böylece git braktif olarak geliştirilmiş dalları git bragöstermek ve "arşivlenmiş" olanlar da dahil olmak üzere tüm dalları göstermek .


5
Bir dalın master ile birleştirilip birleştirilmediği arşiv durumu ile ilgisi yoktur. Örneğin, geliştirici ekibimde, bazı şeyleri test etmek için özel olarak oluşturulmuş birkaç şubemiz var. Bu dalları arşivimizde tutmak istiyoruz, ama kesinlikle onları ustala birleştirmek istemiyoruz.
Bart

4

Şubeleri arşivlemem. Başka bir deyişle, dallar kendilerini arşivler. Arzu ettiğiniz şey arkeologlarla ilgili bilgilerin güvenilir yollarla bulunmasını sağlamaktır. Günlük gelişime yardımcı olmaları ve iş yapma sürecine fazladan bir adım eklememeleri güvenlidir. Yani, insanların bir şubeyle işlendikten sonra bir etiket eklemeyi hatırlayacağına inanmıyorum.

İşte arkeoloji ve gelişime büyük ölçüde yardımcı olacak iki basit adım .

  1. Her görev dalını, basit bir adlandırma kuralı kullanarak sorun izleyicide ilişkili bir sorunla ilişkilendirin .
  2. Her zaman git merge --no-ffgörev dallarını birleştirmek için kullanın ; bu birleştirme taahhüdünü ve tarih balonunu, tek bir işlem için bile istersiniz.

Bu kadar. Neden? Çünkü bir kod arkeolog olarak, bir dalda hangi işin yapıldığını bilmek istemeye nadiren başlarım. Çok daha sık neden çığlık atan dokuz cehennemde kod bu şekilde yazılıyor ?! Kodu değiştirmem gerekiyor, ancak bazı garip özellikleri var ve önemli bir şeyi kırmamak için onları bulmam gerekiyor.

Bir sonraki adım, git blameilişkili taahhütleri bulmak ve daha sonra günlük mesajının açıklayıcı olmasını ummaktır. Daha derine inmem gerekirse, çalışmanın bir dalda yapılıp yapılmadığını öğrenir ve dalı bir bütün olarak okur (konu izleyicideki yorumu ile birlikte).

Diyelim ki git blameXYZ taahhüdünde puanlar. Bir Git geçmişi tarayıcısı açıyorum (gitk, GitX git log --decorate --graph, vb ...), XYZ işini bul ve gör ...

AA - BB - CC - DD - EE - FF - GG - II ...
     \                       /
      QQ - UU - XYZ - JJ - MM

İşte şubem! QQ, UU, XYZ, JJ ve MM'nin hepsinin aynı dalın bir parçası olduğunu biliyorum ve ayrıntılar için günlük iletilerine bakmalıyım. GG'nin birleştirme taahhüdü olacağını ve izleyicide bir sorunla ilişkili olan umarım şubenin adını bileceğini biliyorum.

Herhangi bir nedenle, git logbirleştirme taahhüdünde çalıştırabileceğim ve şube adını arayabileceğim eski bir şube bulmak istersem . Çok büyük depolarda bile yeterince hızlıdır.

Dalların kendilerini arşivlediğini söylediğimde bunu kastediyorum.

Her şubeyi etiketlemek, işlerin yapılmasına gereksiz bir iş ekler (acımasızca düzenlenmesi gereken kritik bir süreç), etiket listesini (performanstan değil, insan okunabilirliğinden) sadece çok nadiren yararlı olan ve olmayan t Arkeoloji için bile çok yararlı.


2
Peki ya dağınıklık? Belki de eski dalları 10 metreküp kir altında saklamanın bir yolu olsaydı.
bvj

1
Bu yararlıdır, ancak birleştirilmemiş dallar için geçerli değildir. Bazen bir dalda bir deneme yapıldı ve daha sonra bir kısmının yararlı olması durumunda içeriği korumak istersiniz.
Neil Mayhew

1
@bvj Bu cevabın her zaman birleştirilmiş şubeleri silmeniz gerektiğini gösteriyor çünkü birleştirme taahhüdü ile onlara her zaman geri dönebilirsiniz. Buna katılıyorum.
Neil Mayhew

@NeilMayhew Evet, bunun gibi yaklaşık 10 birleştirilmemiş şubem var. Her biri açık bir görevle ilişkilidir, böylece ne yaptığımı hatırlayabilirim. Onlarla bir şeyler yapacağım, ya da artık güncel olmadıkları kadar güncel değiller ve onları sileceğim. "Daha sonra ihtiyacım olabilir" dallarında kesinlikle boğulan bir proje üzerinde çalıştım, böylece ne yaptığımızı neredeyse anlayamadık. Bazı geliştiricilerin kendi başlarına temizlemek zorunda kalmamaları gerçekten bir bahane oldu. Biraz rahatlık iyi, ama kontrolden çıkmasına izin vermeyin.
Schwern

@Schwern katılıyorum. Ben de böyle projelerde bulundum. Dalları etiketlere dönüştürmenin dağınıklıktan kurtulmanın iyi bir yolu olduğunu düşünüyorum, çünkü etiketler listesi her zaman büyüyecek, ancak dallar listesi olmamalı (çünkü devam eden iş miktarını temsil ediyor). Etiketler için ad boşluğu kullanmak listeyi daha yönetilebilir hale getirir, ancak paket oranı eğilimlerine kesinlikle direnmek gerekir. Bir geliştirici, başkalarının sonunda kullanması için iyi bir şans olmadığı sürece, taahhütleri kendi makinelerinde tutmalıdır.
Neil Mayhew

2

Yaklaşımım, "trash_" öneki ile umurumda olmayan tüm dalları yeniden adlandırmak, sonra kullanmaktır:

git branch | grep -v trash

(kabuk anahtar bağlama ile)

Aktif dalın rengini korumak için şunlara ihtiyaç vardır:

git branch --color=always | grep --color=never --invert-match trash

2
Şubeleri yeniden adlandırıyorsanız, onları "arşiv /" ad alanına da koyabilirsiniz
qneill

1

Şube sizin için arşivleyecek bir komut dosyası kullanabilirsiniz

archbranch

Ön ek arşiviyle / için bir etiket oluşturur ve ardından dalı siler. Ancak kodu kullanmadan önce kontrol edin.


Kullanım - $/your/location/of/script/archbranch [branchname] [defaultbranch]

Komut dosyasını konumunu yazmadan çalıştırmak istiyorsanız yolunuza ekleyin

Sonra arayabilirsin

$ archbranch [branchname] [defaultbranch]

[defaultbranch]O arşivleme bitince gidecek dalıdır. Renk kodlamasıyla ilgili bazı sorunlar vardır, ancak diğerlerinin çalışması gerekir. Uzun süredir projelerde kullanıyorum, ama hala geliştirilme aşamasında.


1
Yığın Taşması Yardımı başına , ürününüzle olan ilişkinizi açıklamanız gerekir.
LittleBobbyTables - Au Revoir

Üzgünüm bilmiyordum. Senaryonun yazarıyım.
Banezaka

0

Bazen şubeleri şu şekilde arşivlerim:

  1. Yama dosyaları oluşturun, örneğin, format-patch <branchName> <firstHash>^..<lastHash>(firstHash ve lastHash kullanarak git log <branchName>.
  2. Oluşturulan yama dosyalarını bir dosya sunucusundaki dizine taşıyın.
  3. Şubeyi silin, ör. git branch -D <branchName>

Şubeyi tekrar kullanmanız gerektiğinde yamayı “uygulayın”; ancak, yama dosyalarının uygulanması (bkz. git am) hedef dalın durumuna bağlı olarak zor olabilir. Artı tarafta, bu yaklaşım, şubenin taahhütlerinin çöp toplanmasına ve repoda yer kazanmasına izin verme avantajına sahiptir.

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.