Изменить коммит, отправленный на GitHub ... удаление файлов - PullRequest
0 голосов
/ 07 февраля 2019

Мерзавец крутит мой мозг.Но я думаю, что я на полпути с этой проблемой.

Я зафиксировал (дважды) и отправил на GitHub, но первый коммит содержал два файла, которые не должны были быть включены.Итак, я сделал следующее ...

git reset --hard HEAD~2

Это вернуло ГОЛОВУ к первому коммиту с дополнительными файлами.

HEAD is now at 1979096c2

Теперь, если я изменю, сделайте коммит (иСнова нажмите принудительно) с ТОЛЬКО двумя необходимыми файлами, исправляет ли это фиксацию на GitHub?

Чтобы быть более понятным ... первоначальная (неправильная) фиксация содержала 4 файла.Я хочу изменить это, чтобы иметь только 2 файла.Я на правильном пути?

Ответы [ 3 ]

0 голосов
/ 07 февраля 2019

Вместо того, чтобы делать полный сброс, вы также можете выполнить git revert.

git revert <commit_id>

Используйте git log , чтобы обратиться к идентификатору коммита, который вы хотите вернуть.

0 голосов
/ 07 февраля 2019

Нет.

Прежде всего, когда вы говорите «изменить, зафиксировать (и принудительное нажатие)», вы имеете в виду команду git commit --amend?Наименование опции amend может быть немного запутанным.Хотя она и отражает цель команды, она предлагает отредактировать существующий коммит, чего не делает, потому что это невозможно.

То, что у вас есть после сброса, выглядит примерно так

O <--(master)
 \
  A -- B <--(origin/master)

Итак, вы зафиксировали дважды (A и B), но A содержит файлы, которые вам не нужны в репо, поэтому вы сбрасываете назад 2 коммита (до до A),Тогда первое, что нужно понять, это то, что если вы сделаете commit --amend отсюда, это будет вносить поправки в коммит O, а не в фиксацию A.

Но также, что означает «изменить»Коммит, учитывая, что, как я уже говорил выше, вы не можете изменить существующий коммит?Что ж, это означает, что вы создаете новый коммит - у которого есть новый идентификатор - и «заменяете» старый коммит им.Это звучит как раскалывание волос, но это важно, потому что «замена» коммита не делает всего, что вы могли бы предположить, что он сделает.

Предположим, вы сбросили коммит A.В приведенном выше примере это будет git reset --hard master^ (1 коммит до подсказки ветвления - так что вы проверили коммит, который был «неправильным»).Теперь у вас есть

O -- A <--(master)
      \
       B <--(origin/master)

Теперь вы можете редактировать рабочее дерево (т.е. удалять ненужные файлы), а затем вы можете сказать git «изменить» коммит A.Но вы получите

O -- A -- B <--(origin/master)
 \
  C <--(master)

C - это новый коммит с новым идентификатором.Если до commit --amend вы внесли только небольшие изменения, то к применяются в основном те же изменения, что и к O, что и A - но это все еще совершенно отдельный коммит.В истории вашего локального филиала C заменяет A - но только в вашем местном филиале - не во всем хранилище.B по-прежнему видит A как своего родителя, а origin/master по-прежнему указывает на B.

Если вы затем принудительно нажмете, вы переместитесь origin/master в C.Это редактирование истории, которое имеет последствия, если хранилище используется совместно с другими.См. Документацию git rebase в разделе «восстановление после исходной перезагрузки»;этот раздел применим к любому переписыванию, независимо от того, включает ли оно команду rebase.Также обратите внимание, что если вы не правильно координируете принудительный толчок с другими пользователями репо, возможно, что любой из них сделает неправильную вещь при восстановлении и отменит сделанные вами изменения.

Итакв дополнение к замене A на C, эта процедура удаляет B из истории веток, поскольку «замена» A на C не является заменой на месте во всем хранилище.

Вы можете исправить это, изменив B с A на C. Есть несколько способов сделать это, например

git checkout origin/master
git rebase --onto master HEAD^

Это дает вам

O -- A -- B <--(origin/master)
 \
  C -- B' <--(master)

Здесь я использовал нотацию, которая указывает, что новый коммит (B') применяет те же изменения, что и старый коммит (B), относительно новой базы - но это все еще совершенно новый коммит.это перезапись истории, и вам придется координировать свои действия с любыми другими пользователями и принудительно нажимать.

В зависимости от того, почему эти файлы должны быть исключены из репо, также может быть важно знать, что это делает(пока) физически не удалять исходную историю (включая удаленные файлы).Ваш локальный репо будет удерживать их, по крайней мере, до тех пор, пока старая история остается в журнале.Есть шаги, которые вы можете предпринять, чтобы выполнить более раннюю очистку локально;но пульт (в зависимости от того, как он размещен) может иметь или не иметь удобных процедур для удаления файлов оттуда.И ничто из того, что вы можете сделать, не гарантирует удаление файлов из любых других клонов, которые могут существовать.

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

0 голосов
/ 07 февраля 2019

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

...