Bagaimana saya bisa mengarsipkan cabang git?

305

Saya memiliki beberapa cabang lama di repositori git saya yang tidak lagi dalam pengembangan aktif. Saya ingin mengarsipkan cabang sehingga tidak muncul secara default saat berjalan git branch -l -r. Saya tidak ingin menghapusnya, karena saya ingin menyimpan sejarahnya. Bagaimana saya bisa melakukan ini?

Saya tahu bahwa mungkin untuk membuat referensi di luar referensi / kepala. Sebagai contoh refs/archive/old_branch,. Adakah konsekuensi dari melakukan itu?

dan-manges
sumber
git-rm tidak menghapus sumber daya dari repositori, ia hanya menghapusnya dari indeks kernel.org/pub/software/scm/git/docs/git-rm.html Anda dapat dengan mudah mengembalikan sumber daya ini menggunakangit checkout [rev] file
Dana the Sane
1
Tidak yang saya tahu. Saya menggunakan Attic/<branchname>tag ringan untuk mengarsipkan cabang.
Jakub Narębski
tag adalah pilihan yang cepat dan aman dan waras.
kch

Jawaban:

401

Saya percaya cara yang tepat untuk melakukan ini adalah dengan menandai cabang. Jika Anda menghapus cabang setelah Anda memberi tag maka Anda telah menyimpan cabang dengan efektif tetapi itu tidak akan mengacaukan daftar cabang Anda.

Jika Anda perlu kembali ke cabang cukup periksa tag. Ini akan secara efektif mengembalikan cabang dari tag.

Untuk mengarsipkan dan menghapus cabang:

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

Untuk mengembalikan cabang beberapa waktu kemudian:

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

Sejarah cabang akan dipertahankan sama seperti ketika Anda memberi tag itu.

Jeremy Wall
sumber
11
Saya seorang pemula Git, tetapi dalam mencoba ini, saya pikir perintah yang tepat untuk memulihkan cabang adalah:git checkout -b <branchname> archive/<branchname>
Steve
6
Apakah ada alasan untuk tidak menggunakan tag objek dalam kasus ini? Mampu melihat siapa yang diarsipkan cabang dan kapan bisa menarik.
Grégory Joseph
7
@ GrégoryJoseph: Itu yang disebut "tag beranotasi". Dan ya, menggunakan itu bisa membuat banyak akal, kataku.
onnodb
22
catatan kecil, Anda mungkin ingin branch -Dkarena itu mungkin tidak sepenuhnya digabung jika Anda mengarsipkannya dengan cara ini
Arkadiy Kukarkin
5
Sangat bagus. Berikut ini adalah tutorial lengkap dengan penjelasan.
guyaloni
123

Jawaban Jeremy pada prinsipnya benar, tetapi IMHO perintah yang dia tentukan tidak sepenuhnya benar.

Berikut cara mengarsipkan cabang ke tag tanpa harus checkout cabang (dan, karenanya, tanpa harus checkout ke cabang lain sebelum Anda dapat menghapus cabang itu):

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

Dan inilah cara mengembalikan cabang:

> git checkout -b <branchname> archive/<branchname>
Steve
sumber
18
Saya kira Anda belum memiliki poin yang cukup tetapi akan lebih baik ketika Anda lakukan untuk hanya mengedit jawaban yang ada - +1 tetap :)
jkp
5
@jkp mengedit kode dan perintah pengguna lain biasanya disukai karena perubahan halus pada perintah git dapat melakukan hal-hal yang sangat berbeda, dan Anda mungkin tidak mengerti mengapa penulis asli menulis sesuatu seperti yang mereka lakukan. lebih baik buat jawaban sendiri atau tinggalkan komentar.
Dan Bechard
Atau bahkan lebih buruk daripada hal-hal yang berbeda secara drastis, perubahan halus dalam perintah atau kode dapat menyebabkan hasil yang sedikit berbeda, yang bisa sangat sulit untuk dipecahkan, saya sarankan meninggalkan sebagai komentar sehingga poster jawaban dapat mengedit dirinya sendiri atau merespons dengan klaim balik yang mereferensikan hasil yang berpotensi berbeda (Yang klaim klaim semacam itu agak umum)
Nicholas Pipitone
22

Ya, Anda dapat membuat referensi dengan menggunakan awalan non-standar git update-ref. misalnya

  • Arsipkan cabang: git update-ref refs/archive/old-topic topic && git branch -D topic
  • Kembalikan cabang (jika perlu): git branch topic refs/archive/old-topic

Ref dengan awalan non-standar (di sini refs/archive) tidak akan muncul pada biasa git branch, git logatau git tag. Namun, Anda dapat mendaftarkannya dengan git for-each-ref.

Saya menggunakan alias berikut:

[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

Juga, Anda mungkin ingin mengonfigurasi remote seperti push = +refs/archive/*:refs/archive/*untuk mendorong cabang yang diarsipkan secara otomatis (atau git push origin refs/archive/*:refs/archive/*untuk sekali tembak).

Cara lain adalah dengan menuliskan SHA1 di suatu tempat sebelum menghapus cabang, tetapi memiliki keterbatasan. Komit tanpa referensi akan diberikan setelah 3 bulan (atau beberapa minggu tanpa reflog) , apalagi manual git gc --prune. Komit yang ditunjukkan oleh referensi aman dari GC.

Sunting: Ditemukan implementasi perl dari ide yang sama oleh @ap :git-attic

Sunting ^ 2: Menemukan posting blog di mana Gitster sendiri menggunakan teknik yang sama.

snipsnipsnip
sumber
3
Luar biasa, terlepas dari semua orang di utas ini, Anda benar-benar menjawab pertanyaan itu.
tzrlk
20

Memperluas jawaban Steve untuk mencerminkan perubahan pada remote, saya lakukan

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

Untuk memulihkan dari jarak jauh, lihat pertanyaan ini .

Liam
sumber
18

Anda bisa mengarsipkan cabang di repositori lain. Tidak begitu elegan, tapi saya akan mengatakan itu adalah alternatif yang layak.

git push git://yourthing.com/myproject-archive-branches.git yourbranch
git branch -d yourbranch
Lilleaas Agustus
sumber
4
Anda dapat membuat git-bundlealih-alih repositori terpisah.
Jakub Narębski
9

Berikut ini adalah alias untuk itu:

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

Tambahkan seperti ini:

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

Ingatlah bahwa sudah ada git archiveperintah sehingga Anda tidak dapat menggunakan archivesebagai nama alias.

Anda juga dapat menentukan alias untuk melihat daftar cabang 'diarsipkan':

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

tentang menambahkan alias

Alexey
sumber
3
Dengan versi git yang lebih baru (seperti yang disarankan di sini ), alias ini memberikan penyelesaian:!git tag archive/$1 $1 && git branch -D
Kurangnya
5

Saya menggunakan alias berikut untuk menyembunyikan cabang yang diarsipkan:

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

Jadi git bruntuk menunjukkan cabang yang dikembangkan secara aktif dan git brauntuk menunjukkan semua cabang termasuk yang "diarsipkan" .

Pitr
sumber
5
Apakah cabang telah digabung menjadi master tidak ada hubungannya dengan status arsipnya. Sebagai contoh, di tim dev saya, kami memiliki beberapa cabang yang dibuat khusus untuk menguji hal-hal. Kami ingin menyimpan cabang-cabang itu di arsip kami, tetapi kami jelas tidak ingin menggabungkannya menjadi master.
Bart
4

Saya tidak akan mengarsipkan cabang. Dengan kata lain, cabang mengarsipkan diri mereka sendiri. Yang Anda inginkan adalah memastikan informasi yang relevan dengan arkeolog dapat ditemukan dengan cara yang dapat diandalkan. Dapat diandalkan karena mereka membantu pengembangan harian dan tidak menambah langkah ekstra untuk proses menyelesaikan pekerjaan. Artinya, saya tidak percaya orang akan ingat untuk menambahkan tag setelah mereka selesai dengan cabang.

Inilah dua langkah sederhana yang akan sangat membantu arkeologi dan pengembangan.

  1. Tautkan setiap cabang tugas dengan masalah terkait di pelacak masalah menggunakan konvensi penamaan sederhana .
  2. Selalu gunakan git merge --no-ffuntuk menggabungkan cabang tugas; Anda ingin penggabungan komit dan gelembung riwayat, bahkan hanya untuk satu komit.

Itu dia. Mengapa? Karena sebagai seorang arkeolog kode, saya jarang memulai dengan ingin tahu pekerjaan apa yang dilakukan pada cabang. Jauh lebih sering itu sebabnya dalam semua teriakan sembilan neraka adalah kode yang ditulis dengan cara ini ?! Saya perlu mengubah kode, tetapi memiliki beberapa fitur aneh, dan saya perlu memecahkannya untuk menghindari melanggar sesuatu yang penting.

Langkah selanjutnya adalah git blamemenemukan komit terkait dan kemudian berharap pesan log jelas. Jika saya perlu menggali lebih dalam, saya akan mencari tahu apakah pekerjaan itu dilakukan di cabang dan membaca cabang secara keseluruhan (bersama dengan komentarnya di pelacak masalah).

Katakanlah git blamepoin di komit XYZ. Saya membuka browser riwayat Git (gitk, GitX git log --decorate --graph,, dll ...), cari komit XYZ dan lihat ...

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

Ada dahan saya! Saya tahu QQ, UU, XYZ, JJ dan MM semuanya adalah bagian dari cabang yang sama dan saya harus melihat pesan log mereka untuk detailnya. Saya tahu GG akan menjadi gabungan komit dan memiliki nama cabang yang mudah-mudahan dikaitkan dengan masalah di pelacak.

Jika, karena alasan tertentu, saya ingin menemukan cabang lama yang dapat saya jalankan git logdan mencari nama cabang di komit gabungan. Itu cukup cepat bahkan pada repositori yang sangat besar.

Itulah yang saya maksud ketika saya mengatakan bahwa cabang mengarsipkan diri mereka sendiri.

Memberi tag pada setiap cabang menambahkan pekerjaan yang tidak perlu untuk menyelesaikan sesuatu (proses kritis yang harus dirampingkan tanpa ampun), membuat daftar tag (tidak berbicara tentang kinerja, tetapi keterbacaan manusia) dengan ratusan tag yang hanya sekali-sekali berguna, dan bukankah ' Bahkan sangat berguna untuk arkeologi.

Schwern
sumber
2
Tapi bagaimana dengan kekacauan itu? Mungkin jika ada cara untuk menyembunyikan cabang-cabang tua di bawah 10 meter kubik tanah.
bvj
1
Ini berguna, tetapi itu tidak berlaku untuk cabang yang tidak dimurnikan. Terkadang percobaan dilakukan pada cabang dan Anda ingin menyimpan konten untuk berjaga-jaga jika beberapa di antaranya nanti berguna.
Neil Mayhew
1
@ bvj Saya pikir jawaban ini menyarankan Anda harus selalu menghapus cabang gabungan, karena Anda selalu dapat kembali ke mereka melalui komit gabungan. Saya setuju dengan ini.
Neil Mayhew
@NeilMayhew Ya, saya memiliki sekitar 10 cabang yang belum dimurnikan seperti itu yang membuka sendiri. Masing-masing dikaitkan dengan tugas terbuka sehingga saya dapat mengingat apa yang sedang saya lakukan. Saya akan melakukan sesuatu dengan mereka, atau mereka menjadi ketinggalan zaman mereka tidak lagi relevan dan saya akan menghapusnya. Saya mengerjakan proyek yang benar-benar tenggelam dalam cabang "Saya mungkin membutuhkannya nanti" sehingga kami tidak bisa melihat apa yang kami lakukan. Itu benar-benar alasan bagi beberapa devs untuk tidak harus membersihkan diri mereka sendiri. Sedikit kelonggaran baik-baik saja, tetapi jangan biarkan itu lepas kendali.
Schwern
@Schwern saya setuju. Saya pernah mengerjakan proyek seperti itu juga. Saya pikir mengkonversi cabang ke tag adalah cara yang baik untuk menghilangkan kekacauan, karena daftar tag selalu akan bertambah sedangkan daftar cabang tidak boleh (karena itu mewakili jumlah pekerjaan yang sedang berlangsung). Menggunakan namespacing untuk tag membuat daftar lebih mudah dikelola, tetapi kecenderungan paket pasti perlu ditolak. Pengembang harus mempertahankan komit pada mesin mereka sendiri kecuali ada kesempatan baik pada akhirnya orang lain akan menggunakannya.
Neil Mayhew
2

Pendekatan saya adalah mengubah nama semua cabang yang tidak saya pedulikan dengan awalan "trash_", lalu gunakan:

git branch | grep -v trash

(dengan ikatan kunci shell)

Untuk mempertahankan pewarnaan cabang aktif, Anda perlu:

git branch --color=always | grep --color=never --invert-match trash
Sridhar Sarnobat
sumber
2
Jika mengganti nama cabang, Anda mungkin juga meletakkannya di namespace "archive /"
qneill
1

Anda dapat menggunakan skrip yang akan mengarsipkan cabang untuk Anda

archbranch

Itu membuat tag untuk Anda dengan arsip awalan / dan kemudian menghapus cabang. Tetapi periksa kode sebelum Anda menggunakannya.


Penggunaan - $/your/location/of/script/archbranch [branchname] [defaultbranch]

Jika Anda ingin menjalankan skrip tanpa menulis lokasi, tambahkan skrip ke jalur Anda

Maka Anda dapat memanggilnya dengan

$ archbranch [branchname] [defaultbranch]

Ini [defaultbranch]adalah cabang yang akan dituju ketika pengarsipan selesai. Ada beberapa masalah dengan pengkodean warna tetapi selain itu harus bekerja. Saya sudah menggunakannya dalam proyek-proyek untuk waktu yang lama, tetapi masih dalam pengembangan.

Banezaka
sumber
1
Bantuan Per Stack Overflow , Anda perlu mengungkapkan afiliasi Anda dengan produk Anda.
LittleBobbyTables - Au Revoir
Oh, maaf, tidak tahu. Saya adalah penulis naskah.
Banezaka
0

Saya terkadang mengarsipkan cabang sebagai berikut:

  1. Hasilkan file tambalan, misalnya, format-patch <branchName> <firstHash>^..<lastHash>(dapatkan firstHash dan lastHash menggunakan git log <branchName>.
  2. Pindahkan file tambalan yang dihasilkan ke direktori di server file.
  3. Hapus cabang, misalnya, git branch -D <branchName>

"Terapkan" tambalan saat Anda perlu menggunakan cabang lagi; Namun, menerapkan file tambalan (lihat git am) dapat menjadi tantangan tergantung pada keadaan cabang target. Di sisi positifnya, pendekatan ini memiliki manfaat yang memungkinkan komitmen cabang untuk mengumpulkan sampah dan menghemat ruang di repo Anda.

Bill Hoag
sumber