Страницы

Поиск по вопросам

среда, 10 октября 2018 г.

Как реально удалить в git формально удаленные данные?

Допустим, мы хотим взять какой-то проект и откатиться к его началу, напрочь удалив все лишнее.
Казалось бы, что надо удалить все лишние ветки, обрезать оставленную и может быть почистить мусор. Но не тут-то было, git не хочет просто так ничего забывать, а просто делает вид, что информации уже не существует.
Делаем клон:
cd /tmp git clone https://github.com/avp210159/hello avp@wubu:tmp$ cd hello
Поскольку я пользуюсь алиасами из tutorial, то выведу их тут:
avp@wubu:hello$ git config -l user.name=avp user.email=avp210159@gmail.com alias.co=checkout alias.ci=commit alias.st=status alias.br=branch alias.hist=log --pretty=format:"%h %ad | %s%d [%an]" --graph --date=short alias.histt=log --pretty=format:"%h T=%t %ad | %s%d [%an]" --graph --date=short alias.type=cat-file -t alias.dump=cat-file -p core.editor=vi avp@wubu:hello$
Запоминаем всю историю "проекта" с ее SHA
avp@wubu:hello$ git hist --all * 80333c5 2016-06-20 | merge with pull origin (origin/mtime) [avp] |\ | * e86897b 2016-06-17 | mtime in branchmtime on avp-ubu1 [avp] | * f028a44 2016-06-16 | Update README (local version) [avp] | * 9a8ad84 2016-06-14 | fix README merge conflict [avp] | |\ | | * 6502c2b 2016-06-09 | new .mtimes filename and hook script + [avp] | * | 54f9e11 2016-06-14 | change pre-commit description in README [avp] | * | 2f6e07f 2016-06-09 | new .mtimes filename and hook script ++ [avp] | |/ | * 39f7393 2016-06-09 | new .mtimes filename and hook script [avp] | * 7f9be15 2016-06-07 | add BRANCH= to Notes [avp] | * 2c79116 2016-06-07 | restore mtimes in master [avp] | * e572dc2 2016-06-07 | ya some changes in Notes and mtimes script [avp] | * 9430c0f 2016-06-07 | some changes in Notes and mtimes script [avp] | * 33336a8 2016-06-07 | switch to style ... [avp] | * c9d1277 2016-06-07 | delete .gittimes/ from .gitignore [avp] | * 95bc9f3 2016-06-07 | mtimes pre-commit test2 [avp] | * 4d74da9 2016-06-07 | mtimes pre-commit 1-st [avp] | * a929ae6 2016-06-07 | delete .gitimes/, switch to pre-commit .mtimes [avp] | * eeceb8b 2016-06-07 | mtimes in pre-commit (initial test 2 (--amend)) [avp] | * e0debec 2016-06-06 | mtimes sentinel again 3-nd [avp] | * bb90a66 2016-06-06 | mtimes sentinel again 2-nd [avp] | * b8658c0 2016-06-06 | mtimes sentinel again [avp] | * 4a1df91 2016-06-06 | mtimes sentinel 3-st [avp] | * fd787f2 2016-06-06 | mtimes with sentinel 2-nd () [avp] | * f0463c9 2016-06-06 | mtimes with sentinel 1-st [avp] | * 66be459 2016-06-03 | mtime postcommit ./gitimes +n-th mistake [avp] | * 20c41f6 2016-06-03 | mtime postcommit ./gitimes +n-th [avp] | * e9606f8 2016-06-03 | mtime postcommit ./gitimes n-th [avp] | * 204f16f 2016-06-03 | mtime postcommit ./gitimes [avp] | * 44956af 2016-06-03 | mtime postcommit 5-th [avp] | * 114cf75 2016-06-03 | mtime postcommit 4-th [avp] | * 81ddd75 2016-06-03 | mtime with nested commit in postcommit 2-nd [avp] | * 1cc0c8a 2016-06-03 | mtime with nested commit in postcommit 2-nd [avp] | * a59abd9 2016-06-03 | mtime with nested commit in postcommit [avp] | * 312e92b 2016-06-03 | mtime postcommit 3 4 [avp] | * a54cd63 2016-06-03 | mtime postcommit 3 [avp] | * a1aee23 2016-06-03 | mtime postcommit 2 [avp] * | 3c4de65 2016-06-20 | ya commit [avp] * | 307bd84 2016-06-20 | delete .gitimes/... again (was restored at play with history) [avp] * | ce922e3 2016-06-20 | rebase ... try delete a lot of histiry ... [avp] * | 2f7aecd 2016-06-14 | change pre-commit description in README [avp] * | 0dd8e2a 2016-06-09 | new .mtimes filename and hook script ++ [avp] * | 88c5a7d 2016-06-03 | mtime with nested commit in postcommit 2-nd [avp] * | 6ddf211 2016-06-03 | mtime with nested commit in postcommit 2-nd [avp] * | a78f31e 2016-06-03 | mtime postcommit 2 [avp] |/ * a31734c 2016-06-02 | mtime work begins [avp] | * f80dd69 2016-06-20 | Merge branch 'master' of https://github.com/avp210159/hello (HEAD -> master, origin/master, origin/HEAD) [avp] | |\ | | * eb0216f 2016-06-17 | mtime on avp-ubu1 [avp] | * | 3e24a50 2016-06-20 | update a bit Git-Notes master version [avp] | |/ | * a06157e 2016-06-16 | Change README (local master version refer to mtime README) [avp] | * 1e15bc5 2016-06-16 | make mtime branch, restore README & Notes from it [avp] |/ * d4aaa79 2016-05-26 | try .md formatting in README [avp] * b9db73c 2016-05-25 | github push from home OK [Vasily] * 1ff513c 2016-05-25 | change Git-Notes, try PUSH! [avp] * b6a9482 2016-05-25 | change readme, try to pull changes after clone [avp] * f7ae83c 2016-05-25 | hide email [Vasily] * eeac95f 2016-05-25 | add .gitignore ~/.gitconfig as my-home-... [avp] * 566eb66 2016-05-25 | add can do/can't do in Git-Notes [avp] * 213ddd5 2016-05-25 | add README.md for git [avp] * 4e2c742 2016-05-25 | result of curl in Git-Notes [avp] * 57953e4 2016-05-25 | add Git-Notes file [avp] | * 2d6f376 2016-06-17 | mtimes on style avp-ubu1 (origin/style) [avp] | * e312891 2016-06-16 | Update README.md [Vasily] | * d8fb896 2016-06-16 | test .md ref to other file in github in README [avp] | * ae6d0e1 2016-06-14 | Create README in this branch [Vasily] | * a13af39 2016-06-14 | in style mtimes on too [avp] | * 56494cb 2016-06-07 | some changes in .mtimes pre-commit [avp] | * 1a0adf6 2016-06-07 | add .gitignore from master [avp] | * e466e8c 2016-05-24 | Updated index.html [avp] | * c17f477 2016-05-24 | Hello uses style.css [avp] | * 0bfa599 2016-05-24 | Added css stylesheet [avp] |/ * 8a6023f 2016-05-24 | Added index.html. [avp] * a828998 2016-05-24 | Moved hello.html to lib [avp] * ba52194 2016-05-24 | Add author/email [avp] * f9de6a7 2016-05-20 | Added HTML header (tag: v1) [avp] * 8d54403 2016-05-20 | Added standard HTML page tags (tag: v1-beta) [avp] * 05bb38e 2016-05-20 | Edit

tag [avp] * a7da921 2016-05-20 | First Commit [avp] avp@wubu:hello$
Смотрим состояние
avp@wubu:hello$ git st On branch master Your branch is up-to-date with 'origin/master'. nothing to commit, working directory clean avp@wubu:hello$ git br * master
и отсоединяемся от удаленного репозитория
avp@wubu:hello$ git remote rm origin
Снова смотрим историю (теперь уже видна только master ветка)
avp@wubu:hello$ git hist --all * f80dd69 2016-06-20 | Merge branch 'master' of https://github.com/avp210159/hello (HEAD -> master) [avp] |\ | * eb0216f 2016-06-17 | mtime on avp-ubu1 [avp] * | 3e24a50 2016-06-20 | update a bit Git-Notes master version [avp] |/ * a06157e 2016-06-16 | Change README (local master version refer to mtime README) [avp] * 1e15bc5 2016-06-16 | make mtime branch, restore README & Notes from it [avp] * d4aaa79 2016-05-26 | try .md formatting in README [avp] * b9db73c 2016-05-25 | github push from home OK [Vasily] * 1ff513c 2016-05-25 | change Git-Notes, try PUSH! [avp] * b6a9482 2016-05-25 | change readme, try to pull changes after clone [avp] * f7ae83c 2016-05-25 | hide email [Vasily] * eeac95f 2016-05-25 | add .gitignore ~/.gitconfig as my-home-... [avp] * 566eb66 2016-05-25 | add can do/can't do in Git-Notes [avp] * 213ddd5 2016-05-25 | add README.md for git [avp] * 4e2c742 2016-05-25 | result of curl in Git-Notes [avp] * 57953e4 2016-05-25 | add Git-Notes file [avp] * 8a6023f 2016-05-24 | Added index.html. [avp] * a828998 2016-05-24 | Moved hello.html to lib [avp] * ba52194 2016-05-24 | Add author/email [avp] * f9de6a7 2016-05-20 | Added HTML header (tag: v1) [avp] * 8d54403 2016-05-20 | Added standard HTML page tags (tag: v1-beta) [avp] * 05bb38e 2016-05-20 | Edit

tag [avp] * a7da921 2016-05-20 | First Commit [avp] avp@wubu:hello$
Уходим куда-то к началу наших забав:
avp@wubu:hello$ git reset --hard 8a6023f HEAD is now at 8a6023f Added index.html. avp@wubu:hello$ avp@wubu:hello$ git br * master avp@wubu:hello$ git st On branch master nothing to commit, working directory clean avp@wubu:hello$ ll total 32 drwxrwxr-x 4 avp avp 4096 Jun 23 15:53 ./ drwxrwxrwt 15 root root 16384 Jun 23 15:50 ../ drwxrwxr-x 8 avp avp 4096 Jun 23 15:54 .git/ -rw-rw-r-- 1 avp avp 95 Jun 23 15:50 index.html drwxrwxr-x 2 avp avp 4096 Jun 23 15:50 lib/
На всякий случай "почистим" и видим:
avp@wubu:hello$ git gc Counting objects: 69, done. Delta compression using up to 2 threads. Compressing objects: 100% (34/34), done. Writing objects: 100% (69/69), done. Total 69 (delta 25), reused 65 (delta 24) avp@wubu:hello$ git hist --all * 8a6023f 2016-05-24 | Added index.html. (HEAD -> master) [avp] * a828998 2016-05-24 | Moved hello.html to lib [avp] * ba52194 2016-05-24 | Add author/email [avp] * f9de6a7 2016-05-20 | Added HTML header (tag: v1) [avp] * 8d54403 2016-05-20 | Added standard HTML page tags (tag: v1-beta) [avp] * 05bb38e 2016-05-20 | Edit

tag [avp] * a7da921 2016-05-20 | First Commit [avp] avp@wubu:hello$
что все вроде бы ОК.
Но, что если посмотреть на запомненные SHA и ...
avp@wubu:hello$ git co e86897b Note: checking out 'e86897b'.
You are in 'detached HEAD' state. You can look around, make experimental changes and commit them, and you can discard any commits you make in this state without impacting any branches by performing another checkout.
If you want to create a new branch to retain commits you create, you may do so (now or later) by using -b with the checkout command again. Example:
git checkout -b
HEAD is now at e86897b... mtime in branchmtime on avp-ubu1 avp@wubu:hello$ ll total 64 drwxrwxr-x 4 avp avp 4096 Jun 23 15:57 ./ drwxrwxrwt 15 root root 16384 Jun 23 15:50 ../ -rwxrwxr-x 1 avp avp 440 Jun 23 15:57 .cur-mtimes-avp-ubu1-avp* -rwxrwxr-x 1 avp avp 379 Jun 23 15:57 .cur-mtimes-wubu-avp* drwxrwxr-x 8 avp avp 4096 Jun 23 15:57 .git/ -rw-rw-r-- 1 avp avp 17 Jun 23 15:57 .gitignore -rw-rw-r-- 1 avp avp 10980 Jun 23 15:57 Git-Notes -rw-rw-r-- 1 avp avp 95 Jun 23 15:50 index.html drwxrwxr-x 2 avp avp 4096 Jun 23 15:57 lib/ -rw-rw-r-- 1 avp avp 327 Jun 23 15:57 my-home-.gitconfig -rw-rw-r-- 1 avp avp 1054 Jun 23 15:57 README.md avp@wubu:hello$ git br * (HEAD detached at e86897b) master avp@wubu:hello$ git st HEAD detached at e86897b nothing to commit, working directory clean avp@wubu:hello$ tail README.md
echo \#$(date) WD:$(pwd) \($BRANCH $(git rev-parse HEAD)\) > $MTIMES cat $TNEW >> $MTIMES chmod +x $MTIMES rm -f $TNEW git add $MTIMES

it's mtime branch README avp@wubu:hello$ cat .cur-mtimes-wubu-avp #Thu Jun 16 16:11:00 MSK 2016 WD:/home/avp/src/git_tutorial/work/hello (## mtime 9a8ad84f9a085333d05051600dee9d412ad9c7f5) touch -m -t 201606071534.57 '.gitignore' touch -m -t 201606071523.21 'Git-Notes' touch -m -t 201606161610.04 'README.md' touch -m -t 201606021438.31 'index.html' touch -m -t 201606031443.13 'lib/hello.html' touch -m -t 201606021438.31 'my-home-.gitconfig' avp@wubu:hello$
классно... (а ведь хотели-то все лишнее удалить). Кстати, обратите внимание, что мы видим удаленную ветку mtime, а вовсе не удаленную уже часть оставленной ветки master.
Затем возвращаемся назад:
avp@wubu:hello$ git co master Warning: you are leaving 46 commits behind, not connected to any of your branches:
e86897b mtime in branchmtime on avp-ubu1 f028a44 Update README (local version) 9a8ad84 fix README merge conflict 54f9e11 change pre-commit description in README ... and 42 more.
If you want to keep them by creating a new branch, this may be a good time to do so with:
git branch e86897b
Switched to branch 'master' avp@wubu:hello$ ll total 32 drwxrwxr-x 4 avp avp 4096 Jun 23 15:59 ./ drwxrwxrwt 15 root root 16384 Jun 23 15:58 ../ drwxrwxr-x 8 avp avp 4096 Jun 23 15:59 .git/ -rw-rw-r-- 1 avp avp 95 Jun 23 15:50 index.html drwxrwxr-x 2 avp avp 4096 Jun 23 15:59 lib/ avp@wubu:hello$
и опять наслаждаемся самообманом.
Каким образом, не воссоздавая по шагам в новом каталоге новую историю, можно откатить клон, реально удалив все не нужное? (да, я знаю о существовании git-filter-branch, которая все же позволяет Rewrite branches, но как-то это у них сложновато выглядит...).


Ответ

Говоря упрощенно, git gc удаляет устаревшие недостижимые объекты. По-умолчанию, недостижимый объект устаревает через 2 недели. Объект не достижим, если:
Он не входит коммиты некоторой ветки (после сброса ветки master объекты "вверх" по истории стали недостижимыми) На него нет ссылок из reflog. В данном случае, reflog содержит ссылку на f80dd69, появившуюся после клонирования, - она и препятствует очистке.
Поэтому сначала удалим из reflog записи с недостижимыми (в смысле истории веток) объектами:
git reflog expire --expire-unreachable=now --all
Затем удалим мусор, считая недостижимые объекты уже устаревшими, не дожидаясь двух недель:
git gc --prune=now

Комментариев нет:

Отправить комментарий