Чем отличаются мерзавцы и замены? (Сейчас трансплантаты устарели?) - PullRequest
53 голосов
/ 23 июля 2011

На git grafts очень мало вопросов и ответов против replace.В результате поиска [git] + grafts + replace были найдены только два из тех, которые были актуальны из 5. what-are-git-info-grafts-for и git-what-это-graftcommit или-а-трансплантат-ID .Есть также примечание на git.wiki.kernel.org: GraftPoint

Являются ли трансплантаты полностью обгоняющими на replace и filter-branch, или делайтеони все еще нужны для некоторых особых угловых случаев (и обратной совместимости)?

В общем, как они отличаются (например, которые передаются между репозиториями), и как они в целом одинаковы?Я видел, что Линус, похоже, в настоящее время не заботится о трансплантатах в дискуссии о количестве поколений коммитов (от максимального числа родителей до какого-либо корневого сорта) «Трансплантаты уже ненадежны».

РЕДАКТИРОВАТЬ: дополнительная информация найдена.
Поиском www.kernel.org/pub/software/scm/git/docs для graft найдено только 3 результата:

  1. git-filter-branch (1),
  2. v1.5.4.7 / git-filter-branch (1),
  3. v1.5.0.7 / git-svn (1).

Найден немного более широкий поиск RelNotes / 1.6.5.txt , который содержит:

  • refs / replace / иерархию, предназначенную для использования в качествезамена механизма "трансплантатов" с дополнительным преимуществом, заключающимся в том, что его можно передавать через репозитории.

К сожалению, gitrepository-layout (5) isn 'Это еще не актуально с информацией о макете refs / replace / repository (и примечаниями), а также с какой-либо заметкой об устаревании информации / прививок.

Это становится ближе к поддержке того, чем я былчернила, но я бы приветствовал любое подтверждение или разъяснение.

Ответы [ 3 ]

16 голосов
/ 23 июля 2011

В том же обсуждении о Номер поколения фиксации , о котором вы упомянули, Якуб Наребски подтверждает , что трансплантаты являются более проблемной, чемрешение:

прививки настолько ужасны, что я был бы не против выключения номеров поколений, если они используются.
В случае замены объектов вам нужно и не заменять, и заменять генерацию DAGчисла.
[...] Трансплантаты не подлежат передаче, и если вы используете их для отбраковки, а не для добавления истории, они небезопасны для сборки мусора ... Я думаю.

(публикациявсегда заботились с git filter-branch, как показано на этой нити 2008 на рабочем процессе прививки .)

Разница между прививками и git replace лучше всего иллюстрируется этим ТАК вопросом "Установка указателя родительского git на другого родителя" , а комментарии (снова Якуба) отвечают .

Это включает в себя тСсылка на Git1.6.5

Из того, что я понимаю (из GraftPoints ), git replace вытеснил git grafts (если выесть git 1.6.5 или более поздняя версия)

(Jakub :)

  • , если вы хотите переписать историю затем grafts + git-filter-branch(или интерактивная перебазировка, или быстрый экспорт + например, reposurgeon) - способ сделать это.
  • Если вы хотите / должны сохранить историю , тогда git-replace намного превосходит прививку
13 голосов
/ 08 ноября 2013

Если вам нужно переписать родительский коммит, используя git replace, вот как это сделать.

Как отметил Филип Окли, git replace просто заменяет один коммит другим. Чтобы привить родителя к существующему коммиту, вам нужно сначала создать поддельный коммит с правильным родителем.

Скажем, у вас есть две ветки git, которые вы хотите привить:

(a)-(b)-(c) (d)-(e)-(f)

Теперь мы хотим, чтобы (d) был родителем (c). Таким образом, мы создаем замену для (c) с правильным родителем (назовем это c1), затем git replace (c) с (c1). На этих шагах каждая из букв относится к хешу SHA1, представляющему этот коммит.

Чтобы создать новый коммит:

git checkout d
git rm -rf * # remove all files from working direcotry
git checkout c -- . # commit everything from c over top of it
GIT_AUTHOR_DATE="..." GIT_COMMITTER_DATE="..." git commit -m "..." # create replacement commit with date author

Теперь у вас есть коммит (c1), у которого правильный родитель (d). Поэтому все, что нам нужно сделать, это заменить существующий (c) на (c1):

git replace c c1

Теперь ваша история выглядит так:

(a)-(b)-(c1)-(d)-(e)-(f)

Бинго!

7 голосов
/ 03 августа 2013

РЕДАКТИРОВАТЬ: git replace --graft <commit> [<parent>…​] делает то же самое, что и трансплантаты, и это может добавить или удалить родителей. документация гласит:

Создайте прививочный коммит. Новый коммит создается с тем же содержимым, что и , за исключением того, что его родители будут […] вместо родителей . Затем создается замена для замены на вновь созданный коммит.

(я оставляю старый ответ ниже в качестве ссылки.)


AFAIK, есть один вариант использования, который grafts может обрабатывать, но replace не может: добавление или удаление родителей. Это мощный инструмент для рефакторинга истории.

Например, если вы импортируете историю из старого SVN-репозитория в Git, информация о слиянии отсутствует. Что вы можете сделать (и я делал это много раз), это прочитать сообщения фиксации, чтобы узнать, где было выполнено SVN-слияние, и затем использовать Git-трансплантаты, чтобы добавить родителя в коммит слияния.

IIRC, у меня также было несколько случаев, когда я удалял родителя коммита, чтобы сделать его первым коммитом в истории. Создание чистой истории, основанной на нескольких хаотичных старых репозиториях, иногда требует решительных мер (в моем блоге есть некоторые примеры переноса проектов в Git ).

Затем, после того как вы очистите всю историю, вы должны сделать git filter-branch перед публикацией нового репозитория Git.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...