Удалить/скрыть ветки git без удаления истории коммитов

Ситуация:

У меня есть основной репозиторий с основной веткой разработки и множеством «экспериментальных» веток, вырастающих из него (например, exp1 и exp2). Цель этих ветвей эксперимента — служить заполнителями для экспериментов, которые генерируют числовые результаты. Я записываю название ветки (и идентификатор коммита) веток эксперимента, чтобы иметь возможность вернуться к коммитам, чтобы точно увидеть код и историю результатов.

Но теперь появилось так много экспериментальных ветвей, что становится трудно увидеть главное дерево. Итак, я переосмысливаю свою стратегию сохранения заполнителей в коде каждого набора результатов (т. е. каждого эксперимента). Очевидно, я мог бы просто сохранить рабочий каталог в каждой ветке, но было бы неплохо также сохранить историю коммитов.

Возможное решение:

Один из способов справиться с этим — переместить ветки эксперимента в свои собственные независимые репозитории, каждая из которых будет укоренена в дочернем узле соответствующего узла в истории коммитов ветки разработки. Вот иллюстрация того, что я имею в виду:

введите здесь описание изображения

Нажмите здесь, чтобы открыть увеличенную версию изображения (на imgur.com).

Так, например, для ветки exp1 я хотел бы экспортировать коммиты A->B->C в отдельный репозиторий с корнем в коммите A. Затем я могу просто записать хэш фиксации P1, чтобы знать, откуда произошла ветвь exp1.

Вопрос:

Как я могу это сделать?

Лучший вопрос:

С другой стороны, я сильно подозреваю, что есть гораздо лучшая стратегия для выполнения того, что я хочу сделать, а именно: очистить дерево для визуального осмотра, но сохранить заполнители для предыдущих ветвей, чтобы я мог вернуться к ним в случае необходимости. Итак, может ли кто-нибудь порекомендовать стратегию для этого?


person synaptik    schedule 06.08.2014    source источник
comment
Я просто держу отдельное удаленное репозиторий с архивами, в которые помещаю старые ветки, а затем удаляю их из своего локального репозитория.   -  person Ajedi32    schedule 07.08.2014
comment
@Ajedi32 Ajedi32 Звучит как неплохая идея. Как я могу исключить это удаленное репо из команд журнала git? Например, я обычно запускаю git log --oneline --graph --decorate --all. Как я могу изменить эту команду git-log, чтобы не отображать данный пульт?   -  person synaptik    schedule 07.08.2014
comment
Хороший вопрос. Сейчас я сам этим не занимаюсь, так что не уверен. Если узнаешь, обязательно дай мне знать. ;-)   -  person Ajedi32    schedule 07.08.2014
comment
Кроме того, для предлагаемого вами решения вы можете изучить git replace   -  person Ajedi32    schedule 07.08.2014
comment
Просто вопрос: похоже, вы держите ветки exp на случай, если вам нужно будет найти коммит позже. Почему бы вам просто не пометить их, вместо того, чтобы сохранять ветки?   -  person sleske    schedule 07.08.2014
comment
@sleske Может быть, это то, что я должен делать, на самом деле.   -  person synaptik    schedule 07.08.2014
comment
Но теперь появилось так много экспериментальных ветвей, что становится трудно увидеть главное дерево. Что вы имеете в виду под тем, что видите главное дерево? Как вы вообще видите дерево? Вы просто смотрите на вывод git branch и не хотите видеть там все эти дополнительные ветки?   -  person Gabriel Staples    schedule 11.03.2021
comment
^^ Если вы это имеете в виду, вот мой ответ: stackoverflow.com/a/66574807/4561887.   -  person Gabriel Staples    schedule 11.03.2021


Ответы (1)


Вот одна из альтернатив: используйте ссылки, не относящиеся к ветвям, чтобы сохранить подсказки ветвей перед удалением имен ветвей.

Поскольку это ссылки, не относящиеся к ветвям, они не будут отображаться ни в выводе git branch, ни в материалах, отображаемых, например, git log --branches и gitk --branches. Однако они будут отображаться в списках --all и сохранят объекты репозитория.

Чтобы создать или обновить ссылку без ветки, используйте git update-ref. Выберите пространство имен в refs/, которое, по вашему мнению, не будет конфликтовать с каким-либо будущим использованием (текущее использование: refs/heads/ для веток, refs/tags/ для тегов, refs/remotes/ для удаленных веток, refs/notes/ для заметок и refs/stash для тайника).

person torek    schedule 07.08.2014
comment
Я так понимаю, это так называемая сантехническая команда git, и она позволяет вам произвольно создавать (обновлять) ссылки. И heads, tags, remotes, notes и stash на самом деле просто пространства имен для ссылок, которые имеют стандартное распознаваемое значение в git. Верно? - person synaptik; 07.08.2014
comment
@sleske Итак, если у меня есть удаленная ветка с именем origin/run/diss-001, я могу запустить git update-ref archive/run/diss-001 origin/run/diss-001. Затем создается файл .git/archive/run/diss-001, содержащий SHA1 удаленной ветки. Это проблема, что имя моей ветки и новое имя ссылки содержат / символа? - person synaptik; 12.08.2014
comment
@synaptik: косые черты не проблема, но ссылка должна начинаться с refs/, чтобы она отображалась в --all. Обратите внимание, что даже обычные ветки могут иметь косую черту в своих именах, например, git checkout -b bugs/bug1234 для работы над ошибкой # 1234. - person torek; 12.08.2014
comment
Ах-ха! Спасибо. Итак, эта команда должна быть достаточно хорошей? git update-ref refs/archive/run/diss-001 origin/run/diss-001 - person synaptik; 12.08.2014
comment
Да. Просто загляните в будущее, чтобы увидеть, не пытаются ли какие-либо команды или утилиты, которые вы захотите использовать через 5 лет, также использовать пространство имен refs/archive/. :-) (Кажется маловероятным, но тогда, 5 лет назад, кто бы знал, что refs/notes/ будет использоваться?) - person torek; 12.08.2014
comment
@torek: спасибо за ваш ответ и извините, если я верну этот вопрос из мертвых. Мне было интересно, не могли бы вы расширить/улучшить его, добавив, как теперь вы можете перечислить ветки, скажем, refs/archive/. Так же можете добавить пример как вернуть ветку из архива? - person manu3d; 10.03.2016
comment
@manu3d: просто создайте ветку, указывающую на нужный коммит. Помните, что любое обычное имя ветки (до или после такого архивирования) просто указывает на некоторый конкретный идентификатор коммита, который мы затем называем верхушкой ветки. Поскольку ссылка, например, refs/archive/foo также указывает на какой-то конкретный идентификатор фиксации, вы можете просто выполнить git checkout -b restored refs/archive/foo, чтобы создать новую ветку restored (refs/heads/restored), указывающую на эту фиксацию. Что делает его ветвью, так это то, что его имя находится в refs/heads/. Git автоматически обновит его, как только станет текущей веткой. - person torek; 10.03.2016
comment
Спасибо @torek! И как вы перечисляете заархивированные ветки, когда они там? И хотите ли вы, чтобы я отредактировал ваш ответ, включив в него некоторые концепции из вашего ответа мне? - person manu3d; 13.03.2016
comment
Если все ваши заархивированные ветки перечислены в разделе refs/archive/, используйте git for-each-ref refs/archive для их отображения (обратите внимание, что git for-each-ref имеет много аргументов, включая директиву форматирования для управления выводом). Если вы выбрали другое пространство (пространства) имен, вам понадобится что-то хотя бы немного отличающееся. Я не уверен, что ответ здесь нуждается в дополнительной проработке; люди тоже могут читать комментарии. :-) - person torek; 13.03.2016
comment
AFAICT использует ссылку без ветки для этих заархивированных веток, например. ref/archive/heads (чтобы можно было заархивировать и другие вещи) означает, что такие инструменты, как show-branchs, теряются. Или есть способ сделать что-то вроде git show-branches и применить его к союзу refs/heads и refs/archive/heads? И наоборот, есть ли способ, например. глобус, который можно передать в ветки шоу, который говорит все под refs/heads, кроме вещей под refs/heads/archive? - person Krazy Glew; 11.12.2018
comment
@KrazyGlew: насколько я знаю, для этого нет внешнего интерфейса. Внутренне git show-branches в любом случае должен использовать полные имена, поэтому теоретически должно быть легко расширить его, чтобы взять пространство имен для работы. - person torek; 11.12.2018
comment
@KrazyGlew Вы всегда можете создать свою собственную команду, которая перечисляет ваши заархивированные ветки вместе с обычным выводом git show-branches. - person jamesdlin; 27.03.2019
comment
refs/namespaces/ также используется Git и не должен использоваться как пользовательская спецификация. - person kagmole; 11.09.2020
comment
@torek это элегантное решение. Но не ясно, как нажимать и извлекать эти ссылки. Я был бы очень признателен, если бы вы могли привести пример. - person Dmitry Petrov; 13.09.2020
comment
@DmitryPetrov: они могут быть недоступны для отправки (это зависит от принимающего Git, какие refspecs разрешать), но если используемое вами ссылочное пространство имен refs/archive/, просто git fetch --prune <remote> "+refs/archive/*:refs/archive/*" for instance, to override all your own refs/archive/*` с именами из другого Git. Обратите внимание, что это удалит любые refs/archive/* имена, которых у вас нет, поэтому не используйте -p, если это плохо; или получить в другое пространство имен, или указать имена под refs/archive/, или что-то еще, что вы хотели бы. - person torek; 13.09.2020