Як я можу архівувати гілки git?


305

У моєму сховищі git є кілька старих гілок, які вже не активно розвиваються. Я хотів би архівувати гілки так, щоб вони не з’являлися за замовчуванням під час запуску git branch -l -r. Я не хочу їх видаляти, бо хочу зберігати історію. Як я можу це зробити?

Я знаю, що можна створити посилання поза посиланнями / головами. Наприклад, refs/archive/old_branch. Чи є наслідки цього?


git-rm не видаляє ресурси з сховища, він лише видаляє їх з індексу kernel.org/pub/software/scm/git/docs/git-rm.html Ви можете легко відновити ці ресурси за допомогоюgit checkout [rev] file
Dana the Sane

1
Не те, що я знаю. Я використовую Attic/<branchname>легкі теги для архівування гілок.
Якуб Нарубський

Теги - це швидкий і безпечний і розумний вибір.
кч

Відповіді:


401

Я вважаю, що правильним способом цього є тег гілки. Якщо ви видалите гілку після того, як ви позначили її, ви фактично зберегли цю гілку, але вона не буде захаращувати ваш список філій.

Якщо вам потрібно повернутися до відділення, просто перевірте тег. Це ефективно відновить гілку з тегу.

Щоб архівувати та видалити гілку:

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

Щоб відновити відділення через деякий час:

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

Історія філії збережеться точно так само, як була під час позначення її.


11
Я новачок Git, але намагаючись це зробити, я думаю, що правильною командою для відновлення гілки є:git checkout -b <branchname> archive/<branchname>
Стів

6
Чи є якась причина не використовувати об’єкт-тег у цьому випадку? Вміти бачити, хто архівував філію і коли це може бути цікаво.
Григорій Йосиф

7
@ GrégoryJoseph: Це так званий "помічений тег". І так, я б сказав, що використання цього може мати багато сенсу.
onnodb

22
невелика примітка, яку ви, мабуть, хочете, branch -Dоскільки вона, ймовірно, не буде повністю об'єднана, якщо ви архівуєте її таким чином
Аркадій Кукаркін

5
Дуже хороший. Ось повний підручник з поясненнями.
гайялоні

123

Відповідь Джеремі в принципі правильна, але IMHO команди, які він вказує, не зовсім правильні.

Ось як архівувати гілку до тегу, не вимагаючи оформити гілку (і, отже, не потрібно переходити до іншої гілки, перш ніж її можна видалити):

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

А ось як відновити гілку:

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

18
Я думаю, у вас ще не було достатньо балів, але було б краще, коли ви просто відредагуйте існуючу відповідь - хоч +1 все-таки :)
jkp

5
@jkp редагування коду та команд інших користувачів, як правило, нахмуриться, оскільки тонкі зміни в команді git можуть робити різно різні речі, і ви можете не зрозуміти, чому автор-автор написав щось так, як вони зробили. краще просто зробити власну відповідь або залишити коментар.
Ден Бешард

Або навіть гірше, ніж різко різні речі, тонка зміна команд чи коду може призвести до тонко різних результатів, що може бути дуже важко зрозуміти, я б запропонував залишити як коментар, щоб плакат відповіді міг редагувати себе чи відповідати з зустрічною претензією, що посилається на потенційно різні результати (Які такі зустрічні претензії є досить поширеними)
Ніколас Піпітон,

22

Так, ви можете створити ref за допомогою нестандартного префікса за допомогою git update-ref. напр

  • Архівуйте філію: git update-ref refs/archive/old-topic topic && git branch -D topic
  • Відновіть гілку (за потреби): git branch topic refs/archive/old-topic

Посилання з нестандартним префіксом (тут refs/archive) не відображатимуться ні зазвичай git branch, git logні git tag. Тим не менш, ви можете перерахувати їх git for-each-ref.

Я використовую такі псевдоніми:

[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

Крім того, ви можете налаштуватиpush = +refs/archive/*:refs/archive/* віддалені пристрої, як-от автоматичне натискання архівованих гілок (або git push origin refs/archive/*:refs/archive/*для одного знімка).

Інший спосіб - записати SHA1 десь перед видаленням гілки, але він має обмеження. Команди без будь-якого дозволу будуть GC'd через 3 місяці (або пару тижнів без відмови) , не кажучи вже про посібник git gc --prune. Коміти, на які посилаються відповіді, захищені від GC.

Редагувати: Знайшов реалізацію тієї самої ідеї за допомогою @ap :git-attic

Редагувати ^ 2: Знайшов допис у блозі, де сам Гітстер використовував ту саму техніку.


3
Чудово, окрім усіх інших у цій темі, ви насправді відповіли на питання.
tzrlk

20

Розширення Стіва відповіді , щоб відобразити зміни на пульті дистанційного керування, я зробив

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

Щоб відновитись із пульта, див. Це питання .


18

Ви можете архівувати гілки в іншому сховищі. Не дуже елегантно, але я б сказав, що це альтернатива.

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

4
Ви можете створити git-bundleзамість окремого сховища.
Якуб Нарубський

9

Ось псевдонім для цього:

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

Додайте так:

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

Майте на увазі, що git archiveкоманда вже є, тому ви не можете використовувати archiveяк псевдонім ім'я.

Також ви можете визначити псевдонім, щоб переглянути список "архівованих" гілок:

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

про додавання псевдонімів


3
З новішими версіями git (як тут пропонується ) цей псевдонім завершує:!git tag archive/$1 $1 && git branch -D
Відсутність

5

Я використовую такі псевдоніми, щоб приховати заархівовані гілки:

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

Отже, git brпоказувати активно розвинені гілки та git braпоказувати всі гілки, включаючи "архівовані" .


5
Будь галузь об'єднана в головну, це не має нічого спільного з її архівом. Наприклад, у моїй команді розробників у нас є кілька відділень, створених спеціально для тестування матеріалів. Ми хочемо зберегти ці гілки в нашому архіві, але ми точно не хочемо об'єднати їх у головний.
Барт

4

Я б не архівував філії. По-іншому, гілки архівують себе. Що ви хочете - це забезпечити інформацію, що стосується археологів, можна знайти надійними засобами. Надійний тим, що допомагає щоденному розвитку і не додає зайвого кроку до процесу роботи. Тобто, я не вірю, що люди згадають додати тег, коли вони закінчать із гілкою.

Ось два простих кроки, які значно допоможуть археології та розвитку.

  1. Зв’яжіть кожну гілку завдань із пов’язаною проблемою у трекері проблем, використовуючи просту конвенцію іменування .
  2. Завжди використовувати git merge --no-ffдля об'єднання гілок завдань; ви хочете, щоб ця фіксація злиття та міхур історії були навіть для одного.

Це воно. Чому? Тому що, як археолог з питань коду, рідко я починаю з того, щоб знати, яку роботу було зроблено на гілці. Значно частіше саме тому в усіх кричущих дев'яти пеклах код пишеться так ?! Мені потрібно змінити код, але він має деякі дивні функції, і мені потрібно розгадати їх, щоб уникнути зламу чогось важливого.

Наступним кроком є git blameпошук пов'язаних команд, а потім сподівання, що повідомлення журналу є пояснювальним. Якщо мені потрібно копати глибше, я дізнаюся, чи була робота зроблена у гілці, і прочитаю гілку в цілому (разом із коментарем у трекері випуску).

Скажімо, git blameочки на коміті XYZ. Я відкриваю веб-переглядач історії Git (gitk, GitX, git log --decorate --graphі т. Д.), Знаходжу фіксацію XYZ і бачу ...

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

Там моя філія! Я знаю, що QQ, UU, XYZ, JJ та MM - це одна і та ж галузь, і мені слід переглянути деталі їх журналів. Я знаю, що GG буде об'єктом злиття і матиме назву гілки, яка, сподіваємось, асоціюється з проблемою в трекері.

Якщо з якихось причин я хочу знайти стару гілку, я можу запустити git logі шукати ім'я гілки в комісії злиття. Це досить швидко навіть у дуже великих сховищах.

Це я маю на увазі, коли кажу, що філії архівів самі.

Позначення кожної гілки додає непотрібної роботи до виконання справ (критичний процес, який повинен бути безжально впорядкований), розшифровує список тегів (не кажучи про ефективність, але для людської читабельності) сотень тегів, які корисні лише зрідка і не є ' t навіть дуже корисний для археології.


2
А як же з безладом? Можливо, якби був спосіб сховати старі гілки під 10 кубометрів бруду.
bvj

1
Це корисно, але воно не застосовується до безводних гілок. Іноді експеримент робився на гілці, і ви хочете зберегти вміст, якщо частина його стане корисною пізніше.
Ніл Мейхью

1
@bvj Я думаю, що ця відповідь пропонує вам завжди видаляти об'єднані гілки, тому що ви завжди можете повернутися до них через комісію злиття. Я згоден з цим.
Ніл Мейхью

@NeilMayhew Так, у мене є близько 10 нерозбірливих гілок, які відкриваються самі. Кожен асоціюється з відкритим завданням, щоб я міг згадати, що це робив. Я або щось з ними зроблю, або вони стають такими застарілими, що вони вже не актуальні, і я видалю їх. Я працював над проектом, абсолютно потонувши у гілках "мені це знадобиться пізніше", щоб ми навряд чи могли побачити, що ми робимо. Це справді було приводом для деяких чортів не прибирати за собою. Трохи простоти - це добре, але не дозволяйте йому вийти з-під контролю.
Шверн

@Schwern Я згоден. Я теж був на таких проектах. Я думаю, що перетворення гілок у теги - це хороший спосіб позбутися від безладу, оскільки список тегів завжди зростатиме, тоді як список гілок не повинен (тому що це обсяг роботи, що триває). Використання простору імен для тегів робить список більш керованим, але тенденціям packrat, безумовно, потрібно протистояти. Розробник повинен зберігати свої зобов’язання на власній машині, якщо немає хороших шансів, що хтось інший їх використає в підсумку.
Ніл Мейхью

2

Мій підхід полягає в перейменуванні всіх галузей, які мене не цікавлять, з префіксом "trash_", а потім використовувати:

git branch | grep -v trash

(із прив’язкою ключа оболонки)

Щоб зберегти забарвлення активної гілки, потрібно:

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

2
Якщо перейменувати гілки, ви можете також помістити їх у простір імен "archive /"
qneill

1

Ви можете використовувати сценарій, який буде архівувати відділення для вас

архівний відділ

Він створює для вас тег з архівом префікса /, а потім видаляє гілку. Але перевірте код, перш ніж використовувати його.


Використання - $/your/location/of/script/archbranch [branchname] [defaultbranch]

Якщо ви хочете запустити скрипт, не записуючи його, додайте його до свого шляху

Тоді ви можете подзвонити по телефону

$ archbranch [branchname] [defaultbranch]

Це [defaultbranch]галузь, до якої вона піде, коли буде зроблено архівування. Існують деякі проблеми з кольоровим кодуванням, але інші, ніж це має працювати. Я давно його використовую в проектах, але він все ще знаходиться на стадії розробки.


1
Довідка щодо переповнення штабелю потрібно розкрити свою приналежність до вашого продукту.
LittleBobbyTables - Au Revoir

О, вибачте, не знав. Я автор сценарію.
Банедзака

0

Я інколи архівую філії так:

  1. Створіть файли патчів, наприклад, format-patch <branchName> <firstHash>^..<lastHash>(отримати firstHash та lastHash за допомогою git log <branchName>.
  2. Перемістіть створені файли патчів у каталог на файловому сервері.
  3. Видаліть гілку, наприклад, git branch -D <branchName>

"Застосувати" патч, коли вам потрібно знову використовувати гілку; однак застосування файлів патчів (див. git am) може бути складним залежно від стану цільової гілки. З іншого боку, такий підхід має перевагу тим, що дозволяє філії філій збирати сміття та економити місце у вашому РЕПО.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.