Те, що ви хочете зробити, є дуже руйнівним, якщо ви опублікували історію іншим розробникам. Про необхідні кроки після відновлення історії див. Розділ «Відновлення з верхньої версії» в git rebase
документації .
У вас є щонайменше два варіанти: git filter-branch
та інтерактивна база даних, обидва пояснені нижче.
Використання git filter-branch
У мене була схожа проблема з об'ємними даними бінарних тестів із імпорту Subversion, і я писав про видалення даних із сховища git .
Скажімо, ваша історія git така:
$ git lola --name-status
* f772d66 (HEAD, master) Login page
| A login.html
* cb14efd Remove DVD-rip
| D oops.iso
* ce36c98 Careless
| A oops.iso
| A other.html
* 5af4522 Admin page
| A admin.html
* e738b63 Index
A index.html
Зауважте, що git lola
це нестандартний, але дуже корисний псевдонім. За допомогою --name-status
перемикача ми можемо побачити модифікації дерева, пов’язані з кожним комітом.
У комітеті "Недбале" (чиє ім'я об'єкта SHA1 це ce36c98) файл oops.iso
- це DVD-рип, доданий випадково та видалений у наступній комісії, cb14efd. Використовуючи техніку, описану у вищезгаданому дописі блогу, командою для виконання є:
git filter-branch --prune-empty -d /dev/shm/scratch \
--index-filter "git rm --cached -f --ignore-unmatch oops.iso" \
--tag-name-filter cat -- --all
Параметри:
--prune-empty
видаляє коміти, які стають порожніми ( тобто не змінюють дерево) в результаті роботи фільтра. У типовому випадку ця опція дає більш чисту історію.
-d
називає тимчасовий каталог, який ще не існує для використання для побудови відфільтрованої історії. Якщо ви працюєте на сучасному дистрибутиві Linux, вказівка дерева в дереві /dev/shm
призведе до швидшого виконання .
--index-filter
є основною подією та працює проти індексу на кожному кроці історії. Ви хочете видалити, oops.iso
де б він не був знайдений, але він присутній у всіх комісіях. Команда git rm --cached -f --ignore-unmatch oops.iso
видаляє DVD-рип, коли він присутній, і не виходить з ладу.
--tag-name-filter
описується, як переписати імена тегів. Фільтр cat
- це операція ідентичності. У вашому сховищі, як і в наведеному вище прикладі, може не бути тегів, але я включив цю опцію для повної загальності.
--
вказує кінець параметрів для git filter-branch
--all
далі --
- стенограма для всіх посилань. У вашому сховищі, як і в наведеному вище зразку, може бути лише одна посилання (головний), але я включив цю опцію для повної загальності.
Після певного розбиття історія зараз:
$ git lola --name-status
* 8e0a11c (HEAD, master) Login page
| A login.html
* e45ac59 Careless
| A other.html
|
| * f772d66 (refs/original/refs/heads/master) Login page
| | A login.html
| * cb14efd Remove DVD-rip
| | D oops.iso
| * ce36c98 Careless
|/ A oops.iso
| A other.html
|
* 5af4522 Admin page
| A admin.html
* e738b63 Index
A index.html
Зауважте, що новий комітет "Недбале" додає лише other.html
те, що команда "Видалити DVD-видобуток" більше не знаходиться на головній гілці. Позначена гілка refs/original/refs/heads/master
містить ваші оригінали, якщо ви допустили помилку. Щоб видалити його, виконайте кроки в "Контрольний список для зменшення сховища".
$ git update-ref -d refs/original/refs/heads/master
$ git reflog expire --expire=now --all
$ git gc --prune=now
Для більш простої альтернативи клонуйте сховище, щоб відкинути небажані біти.
$ cd ~/src
$ mv repo repo.old
$ git clone file:///home/user/src/repo.old repo
Використання file:///...
URL-адреси клонування копіює об'єкти, а не створює лише жорсткі посилання.
Тепер ваша історія:
$ git lola --name-status
* 8e0a11c (HEAD, master) Login page
| A login.html
* e45ac59 Careless
| A other.html
* 5af4522 Admin page
| A admin.html
* e738b63 Index
A index.html
Імена об'єктів SHA1 для перших двох комітетів ("Індекс" та "Сторінка адміністратора") залишилися однаковими, оскільки операція фільтрації не змінила цих комісій. «Careless» втратив oops.iso
і «Логін сторінка» отримали новий батько, так що їх SHA1s зробив зміни.
Інтерактивна база даних
З історією:
$ git lola --name-status
* f772d66 (HEAD, master) Login page
| A login.html
* cb14efd Remove DVD-rip
| D oops.iso
* ce36c98 Careless
| A oops.iso
| A other.html
* 5af4522 Admin page
| A admin.html
* e738b63 Index
A index.html
ви хочете видалити oops.iso
з "Недбалого" так, ніби ви його ніколи не додавали, і тоді "Видалити DVD-rip" для вас марний. Таким чином, наш план переходить до інтерактивної бази даних - це зберегти "сторінку адміністратора", відредагувати "Недбало" та відмовитись "Видалити DVD-rip".
Запуск $ git rebase -i 5af4522
запускає редактор із наступним вмістом.
pick ce36c98 Careless
pick cb14efd Remove DVD-rip
pick f772d66 Login page
# Rebase 5af4522..f772d66 onto 5af4522
#
# 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
#
# If you remove a line here THAT COMMIT WILL BE LOST.
# However, if you remove everything, the rebase will be aborted.
#
Виконуючи наш план, ми його модифікуємо
edit ce36c98 Careless
pick f772d66 Login page
# Rebase 5af4522..f772d66 onto 5af4522
# ...
Тобто, ми видаляємо рядок із "Видалити DVD-rip" і змінюємо операцію на "Недбале", edit
а не на pick
.
Збереження-вихід із редактора скидає нас у командний рядок із наступним повідомленням.
Stopped at ce36c98... Careless
You can amend the commit now, with
git commit --amend
Once you are satisfied with your changes, run
git rebase --continue
Як повідомляється в повідомленні, ми перебуваємо на «необережному» зобов'язанні, яке ми хочемо відредагувати, тому ми виконуємо дві команди.
$ git rm --cached oops.iso
$ git commit --amend -C HEAD
$ git rebase --continue
Перший видаляє обраний файл з індексу. Другий модифікує або доповнює "Недбалий", щоб бути оновленим покажчиком, і -C HEAD
вказує git повторно використовувати старе повідомлення. Нарешті, git rebase --continue
йде вперед з рештою операції ребасті.
Це дає історію:
$ git lola --name-status
* 93174be (HEAD, master) Login page
| A login.html
* a570198 Careless
| A other.html
* 5af4522 Admin page
| A admin.html
* e738b63 Index
A index.html
що ви хочете.