Удалить файл из всей истории git - PullRequest
0 голосов
/ 25 сентября 2018

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

Так вот в чем проблема:

Я клонировал репозиторий и добавил в него папку для работы.В эту папку я добавил файлы .csv и .py, которые используют файлы csv.Я пытался выдвинуть это, но понял, что это занимает много времени, так как 2 CSV-файла очень большиеПоэтому я

git rm files

и затем фиксирую.Я попытался нажать еще раз, и только тогда понял, что удаление файла не удаляет его из истории git .// Итак, теперь с последнего завершенного нажатия у меня есть 2 коммита: 1, где я добавил файлы, 1, где я удалилнекоторые .csv.

Я хотел бы, чтобы ваша помощь удалила последние 2 коммита.Это возможно?Спасибо

Ответы [ 3 ]

0 голосов
/ 25 сентября 2018

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

Один пример ..... скажем, я добавил файл .txt на мастер ~ 2.Я больше не хочу этого в истории.

git checkout master~2 git rm --cached a.txt git commit --amend --no-edit git cherry-pick master~2..master git branch -f master # point master in this revision git checkout master

Этого должно быть достаточно.

0 голосов
/ 25 сентября 2018

... Я хотел бы ... удалить последние 2 коммита.Это возможно?

Вы не можете удалить коммиты, но вы можете легко сказать Git забыть их.

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

Если мы позволим одиночным заглавным буквам заменять хэш-идентификаторы коммитов, мы можем нарисовать эту цепочку:

... <-F  <-G  <-H   <--master

Обратите внимание, что имя ветви , master в этом случае хранит хэш-идентификатор последнего коммита в цепочке.(Когда что-то хранит хеш-идентификатор коммита, мы говорим, что эта вещь указывает на коммит, отсюда и стрелки. Имя master указывает на H, H указывает на Gи т. д.)

Способ, которым Git находит эти коммиты, заключается в считывании хеш-идентификатора H из master, который находит коммит H, затем чтении коммита H и его показе,Затем, прочитав H, Git имеет хеш-идентификатор commit G, поэтому Git может прочитать G и показать его и т. Д.

Когда мы делаем новый коммит, Git фактически делаетэто:

  • запись снимка;
  • запись автора и сообщения журнала и т. д .;
  • с новой точкойвернуться к текущему коммиту;
  • и последнему, но наиболее важному, записать хэш-идентификатор нового коммита в имя ветви.

Так что если у нас было:

...--F--G--H

и мы добавили --I:

...--F--G--H--I

, то Git изменил имя master для храненияидентификатор хеша коммита I.В конечном итоге мы имеем:

...--F--G--H--I--J   <-- master

Если мы сделали несколько нежелательных коммитов, мы можем сказать Git: Переустановить имя master, чтобы оно указывало на фиксацию H вместо фиксации J. Есть несколько способов сделать это, но первый, к которому нужно обратиться, в этом случае - git reset --hard (хотя у нас проверено master, и убедитесь, что у вас нет ничего интересногопроигрыш, потому что git reset --hard говорит Git выбросить все из):

git checkout master
git reset --hard HEAD~2

Суффикс ~2 говорит Git, чтобы он отсчитывал два шага - технически, два первого родителя шагов, которые имеют значение, когда у нас есть несколько коммитов слияния в нашей цепочке, но здесь мы этого не делаем, это не имеет значения.Если master в настоящее время указывает на J, то Git будет считать дважды: J до I, затем I до H.Затем Git заменяет нашу работу содержимым из commit H и делает имя, master, указывающее на H вместо J:

             I--J
            /
...--F--G--H   <-- master

Теперь, когдаJ трудно найти , он кажется подлежащим удалению.

Недостатком этого является то, что если у нас есть наш Git, скажем другому Git: Здесь, возьмите копии коммитов I и J, , которые другие Git имеют в двух коммитах и ​​ повторно представят их нашему Git даже после того, как наш Git забыл их,Но если мы никогда не отправляли два коммита где-либо еще, мы единственные, у кого есть их, поэтому, если мы забудем их, они так же хороши, как пропали.

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

0 голосов
/ 25 сентября 2018

Первый пример в документе git filter-branch очень подходит для вашего контекста.Взгляните ( source ):

Предположим, вы хотите удалить файл (содержащий конфиденциальную информацию или нарушение авторских прав) из всех коммитов:

git filter-branch --tree-filter 'rm filename' HEAD
# and see also the variant further in the example description
git filter-branch --index-filter 'git rm --cached --ignore-unmatch filename' HEAD

(см. Подробности на странице документа, я воздержался от копирования и вставки всего этого здесь)

...