2016-05-03 10 views
3

Я просмотрел информацию об авторе. вверх по первому фиксации.Как удалить первую и только фиксацию, если она является единственной фиксацией в ветке?

Однако, похоже, что большинство операций по восстановлению или древовидной структуре полагаются на некоторые другие уже существующие.

Даже когда я запускаю интерактивную команду rebate Git, все, что я вижу в своем маленьком списке коммитов, - это одна строка, «noop». :/(Раскрыто это, запустив мой перебазироваться против дерева Git и root с git rebase -i --root, но удаление линии для первой фиксации я сделал на самом деле не удалить его из дерева.)

перебазирования на вершине root, или первого commit, не работает.

[[email protected] vagrant]$ git rebase -i HEAD~1 
fatal: Needed a single revision 
invalid upstream HEAD~1 
[[email protected] vagrant]$ git rebase -i HEAD 
Unknown command: rnoop 
Please fix this using 'git rebase --edit-todo'. 
[[email protected] vagrant]$ git rebase --edit-todo 
[[email protected] vagrant]$ git rebase --abort 

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

Delete commits from a branch in Git

Этот другой ответ (How do you undo the last commit?) привело к следующему:

[[email protected] vagrant]$ git reset --soft HEAD~ 
fatal: ambiguous argument 'HEAD~': unknown revision or path not in the working tree. 
Use '--' to separate paths from revisions, like this: 
'git <command> [<revision>...] -- [<file>...]' 
[[email protected] vagrant]$ git reset --soft HEAD 

Здесь, для тех, кто еще читает это, это буфер ВИМ с noop я уже говорил ранее:

noop 

# Rebase 3d1c632..3d1c632 onto 3d1c632 (1 command(s)) 
# 
# Commands: 
# p, pick = use commit 
# r, reword = use commit, but edit the commit message 
# e, edit = use commit, but stop for amending 
# s, squash = use commit, but meld into previous commit 
# f, fixup = like "squash", but discard this commit's log message 
# x, exec = run command (the rest of the line) using shell 
# 
# These lines can be re-ordered; they are executed from top to bottom. 
# 
# If you remove a line here THAT COMMIT WILL BE LOST. 
# 
# However, if you remove everything, the rebase will be aborted. 
# 
# Note that empty commits are commented out 

Для тех, кому интересно, почему я не просто редактировать файлы и заново добавить их к совершению, или что-то, я имел неправильную информацию об авторе, который я исправил только после того, как я был запустите «git commit», и я изменил информацию об авторе, пока у меня появилось сообщение commit для редактирования.

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

Плюс, если я не удаляю всю папку .git, я держу свои крючки и прочее, и у меня есть ощущение, что ответы на этот вопрос будут говорить о фундаментальных принципах проектирования в Git, которые я еще не могу понять ,

+1

, если вы сделали ставку на сингл, только совершите транзакцию в своем репо. Не могли бы вы использовать 'git commit -amend'? я, скорее всего, неправильно понимаю базу вашей проблемы. – castis

ответ

3

Вы можете перебазироваться на вершине --root:

git rebase -i --root 

просто изменить автора на последней фиксации, используйте:

git commit --amend --no-edit --author="The Name <[email protected]>" 
+0

//, 'git commit --amend --no-edit --author =" ... ', 'Twerked, в каталоге верхнего уровня проекта записано следующее:' $ git commit --amend --no-edit --author = "Nathan Bassanese <[email protected]>" 'Однако,' git rebase -i -root', не так много. После того как я удалил фиксацию в интерактивной rebase, она все еще была там. –

+0

//, После того, как я попытался удалить строку фиксации в интерактивной rebase, я попытался применить «fixup», чтобы увидеть, что это как-то удалит запись в журнале: '[vagrant @ localhost vagrant] $ git rebase -i -root' ' Can not «fixup» без предыдущей фиксации ... но это не получилось. В любом случае, спасибо за продуманный ответ, но я не думаю, что могу, с чистой совестью, отметить это как принятое, пока не смогу успешно его протестировать. –

+0

// Примечательно, что команда 'git commit' с флагами' --amend' и '--author' изменила фиксацию в одной ветви, но не в другой. Мне пришлось r un it на каждой ветви. –

2

Я вижу, что вы работали по механике фиксации один конкретный вопрос.

Я попытаюсь рассмотреть ваши более общий вопрос, хотя:

... У меня есть ощущение, что ответы на такого рода вопросы будут говорить с фундаментальными принципами дизайна в Git, что я, возможно, еще не понял ,

Вот все сложные штучки, связанные с этим конкретным процессом.

  1. Branch имена (как master) кочующий указатели, которые указывают на один конкретной фиксации.
  2. Каждая фиксация указывает на ее родительский фиксатор (ы). A root commit, по определению, не имеет родителя. (Не применимо здесь, но полезно знать: а слияние коммит просто определяется как любой совершить, по крайней мере, двух родителей.)
  3. Чтобы создать любой совершить, мы должны быть на ветке, но создайте корень , у которого нет родителя, нам нужно, чтобы ветвь не имела коммитов, но смотри точку № 1: имя ветки указывает на фиксацию.
  4. Rebase работает, повторяя git cherry-pick операции, на анонимной ветке, выращенной с --onto цель. (После повторного набора вишни новый анонимный наконечник наконечника заменяет первоначальную фиксацию наконечника ветви, т. Е. Мы перенаправляем ветвь на новый наконечник.)
  5. Один git cherry-pick работает, отличая фиксацию от ее родитель. Например, если родительский файл имеет три файла, а выбранная команда имеет четыре, коммит добавляет новый файл. Если только один из трех переносимых файлов отличается, то все, что изменилось в этом одном файле, составляет остальную часть этого фиксации (ну, и автор комманды, и другие метаданные тоже: они также переносятся в вишнево- выбирать). Перевернув исходную фиксацию в набор изменений, Git затем применяет то же самое: изменяет на другой (уже существующий) совершает и совершает новый коммит из этого. Родитель новой фиксации - это другой фиксатор.

Эти принципы создают Gordian knot that --root slices through. Стоит также отметить, что --root был новым в Git версии 1.6.2 и сильно модифицирован в 1.7.12 (я смутно вспоминаю использование rebase до этого и сталкиваясь с некоторыми проблемами).

Git всегда приходилось решать напряженность между # 1 и # 3 (само решение было улучшено и правильно оформлено в какой-то момент, когда git checkout произвел опцию --orphan). Трюк здесь заключается в том, что, когда на том, что называется «нерожденным ветвью», Git записывает текущую ветвь имя в HEAD, как обычно, но оставляет само название ветви не созданным.

(Здесь это помогает знать, хотя это детали реализации, о которых вы не должны беспокоиться, - что указатели ветвей в настоящее время хранятся в одном или обоих местах. Git хранит эти сопоставления от имени к идентификатору в отдельных небольших файлах в .git/refs/ и/или одного плоском текстовом файле, .git/packed-refs. Если имя ветви ни в одном месте, но в HEAD, Git считает, что этим «нерожденная ветвью».)

Когда делаете new commit, если текущее состояние «на неродившейся ветке», Git делает корневую фиксацию. Новый идентификатор фиксации становится идентификатором для теперь созданной ветви, и теперь мы выходим из самопротиворечивого состояния пребывания на ветке, но не имея фиксации.

У нас по-прежнему возникает проблема, связанная с тем, что git cherry-pick работает, сравнивая фиксацию с ее родителем. Вот почему, если вы хотите, чтобы вишня выбрала фиксацию слияния, вы должны указать , который: parent: слияние - это фиксация с двумя или более родителями, поэтому неясно, какой из них следует противопоставить.Но как насчет корневой фиксации со всеми ее нулевыми родителями?

Git решает эту проблему, сравнивая полученную от вишни корневую команду против the empty tree. Поскольку пустое дерево пустое, каждый файл добавляется снова, и это правильный результат для вишневого кирка.

Следовательно, для переустановки с --root мы хотели бы создать сиротскую ветвь, а затем вишню выбрать корневую фиксацию, а затем все остальные коммиты, как обычно. Но git rebase использует анонимный филиал. Единственный нормальный способ создания сиротской ветви - на имя, но rebase использует режим «отсоединенный HEAD». Кроме того, каждый вишневый выбор, включая первый, должен применять изменения к существующей фиксации, но для создания нового корневого коммита мы должны избегать использования какого-либо существующего родителя.

Сложные внутренности для этого найдены (косвенно) в this answer from VonC, что ссылается на this commit to the Git code. Сценарий rebase делает поистине пустую корневую фиксацию (используя пустое дерево и внутреннюю команду «сантехника» git commit-tree, которая создает объект фиксации с указанными пользователем родительскими идентификаторами), а затем генерирует внутреннюю операцию «сквош», чтобы вишневый выбор существующего root commit (с вишневым киркой, отличающимся от того же пустого дерева) и объединить его с фиктивным пустым корневым фиксатором.

(Здесь также помогает отметить, что «сквош» операция во время перебазирования означает «изменить предыдущий коммит», а-ля git commit --amend. --amend операции указует git commit сделать новый коммит-существующий не может быть изменен, но чтобы родители нового коммита соответствовали родителям существующей фиксации. Это приводит к удалению старого фиксации в сторону: ветвь теперь указывает на новую фиксацию, которая указывает на родителя (ов) с исправленной версией. в хранилище, но если нет другого способа его найти, то уже нет .)

(Этот двухэтапный трюк означает, что информация об авторстве обрабатывается специально.)


Для целей этого требования, по крайней мере, находясь в режиме отдельных головки (после того, как git checkout hash или git checkout --detach branchname, например) рассчитывает как на специальной анонимной ветви, чей наконечник тока фиксации хеш ,

+0

//, я собираюсь прочитать это, когда мне поспать больше, но мое первое впечатление заключается в том, что моя трудность в устранении «первого» совершения происходит из противоречия между пунктом № 1 и пунктом № 3 выше. Спасибо, что привлек мое «пустое дерево» и задумчивый ответ. –

+2

Git «решает», что, не позволяя указателю ветки двигаться до тех пор, пока не произойдет замещение фиксации, т. Е. Никогда не будет фактически удалять это первое когда-либо совершение. (Фактически, за исключением 'git gc' и его сантехники, git никогда не удаляет * никаких * коммитов или любых других объектов. Он строится вокруг * добавления нового материала *, без каких-либо изменений каких-либо существующих объектов. хэшей, которые чувствительны к содержимому.) Когда план должен начинаться с существующей фиксации 'E' и добавлять новые зависящие от вишней коммиты, и ваш первый результат выбора должен быть без родителя, у вас есть проблема. :-) – torek

+0

//, я предполагаю, что окончательный ответ на вопрос, могу ли я удалить, что первая фиксация будет твердой «нет», то? –