Те, що ви хочете зробити, є дуже руйнівним, якщо ви опублікували історію іншим розробникам. Про необхідні кроки після відновлення історії див. Розділ «Відновлення з верхньої версії» в 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
що ви хочете.