Короткий ответ: Commets C3
и C4
останутся в базе данных объектов Git, пока не будут собраны мусор.
Долгий ответ: сбор мусора будет происходить автоматически различными командами фарфора Git или при сборке явного сбора мусора. Существует много сценариев, которые могут вызвать автоматическую сборку мусора; посмотрите на gc.*
configuration settings, чтобы получить представление об этом. Вы можете явно собирать габарит, используя git gc
builtin command. Давайте посмотрим на пример, чтобы узнать, что произойдет.
Прежде всего, давайте настроим нашу среду (я использую Linux, внеся необходимые изменения для вашей среды), поэтому мы надеемся получить одни и те же хэши объектов в разных хранилищах Git.
export GIT_AUTHOR_NAME='Wile E. Coyote'
export [email protected]
export GIT_AUTHOR_DATE=2015-01-01T12:00:00
export GIT_COMMITTER_NAME='Roadrunner'
export [email protected]
export GIT_COMMITTER_DATE=2015-01-01T12:00:00
Поскольку совершающие объект хэши генерируются с использованием этой информации, если мы будем использовать тот же автор и коммиттер ценности, мы все должны теперь получить те же хэши.
Теперь давайте инициализировать функцию для регистрации информации об объекте с помощью git log
, git reflog
, git count-objects
, git rev-list
и git fsck
.
function git_log_objects() {
echo 'Log ...'
git log --oneline --decorate
echo 'Reflog ...'
git reflog show --all
echo 'Count ...'
git count-objects -v
echo 'Hashes ...'
# See: https://stackoverflow.com/a/7350019/649852
{
git rev-list --objects --all --reflog
git rev-list --objects -g --no-walk --all
git rev-list --objects --no-walk $(
git fsck --unreachable 2>/dev/null \
| grep '^unreachable commit' \
| cut -d' ' -f3
)
} | sort | uniq
}
Теперь давайте инициализируем репозиторий Git.
git --version
git init
git_log_objects
, которые для меня, выходов:
git version 2.4.0
Initialized empty Git repository in /tmp/test/.git/
Log ...
fatal: bad default revision 'HEAD'
Reflog ...
fatal: bad default revision 'HEAD'
Count ...
count: 0
size: 0
in-pack: 0
packs: 0
size-pack: 0
prune-packable: 0
garbage: 0
size-garbage: 0
Hashes ...
Как и следовало ожидать, у нас есть инициализированное хранилище без каких-либо объектов в нем. Давайте сделаем некоторые коммиты и посмотрим на объекты.
git commit --allow-empty -m C1
git commit --allow-empty -m C2
git tag T1
git commit --allow-empty -m C3
git commit --allow-empty -m C4
git commit --allow-empty -m C5
git_log_objects
Который дает мне следующий вывод:
[master (root-commit) c11e156] C1
Author: Wile E. Coyote <[email protected]>
[master 10bfa58] C2
Author: Wile E. Coyote <[email protected]>
[master 8aa22b5] C3
Author: Wile E. Coyote <[email protected]>
[master 1abb34f] C4
Author: Wile E. Coyote <[email protected]>
[master d1efc10] C5
Author: Wile E. Coyote <[email protected]>
Log ...
d1efc10 (HEAD -> master) C5
1abb34f C4
8aa22b5 C3
10bfa58 (tag: T1) C2
c11e156 C1
Reflog ...
d1efc10 refs/heads/[email protected]{0}: commit: C5
1abb34f refs/heads/[email protected]{1}: commit: C4
8aa22b5 refs/heads/[email protected]{2}: commit: C3
10bfa58 refs/heads/[email protected]{3}: commit: C2
c11e156 refs/heads/[email protected]{4}: commit (initial): C1
Count ...
count: 6
size: 24
in-pack: 0
packs: 0
size-pack: 0
prune-packable: 0
garbage: 0
size-garbage: 0
Hashes ...
10bfa58a7bcbadfc6c9af616da89e4139c15fbb9
1abb34f82523039920fc629a68d3f82bc79acbd0
4b825dc642cb6eb9a060e54bf8d69288fbee4904
8aa22b5f0fed338dd13c16537c1c54b3496e3224
c11e1562835fe1e9c25bf293279bff0cf778b6e0
d1efc109115b00bac9d4e3d374a05a3df9754551
Теперь у нас есть шесть объектов в хранилище: пять фиксаций и одно пустое дерево. Мы можем видеть, что у Git есть ветвь, тег и/или ссылки reflog на все пять объектов commit. Пока Git ссылается на объект, этот объект не будет собираться мусором. Явное использование коллекции габарей приведет к тому, что объекты не будут удалены из репозитория. (Я останусь проверять это как упражнение для вас.)
Теперь давайте удалим ссылки Git на ссылки C3
, C4
и C5
.
git reset --soft T1
git reflog expire --expire=all --all
git_log_objects
Какие выходы:
Log ...
10bfa58 (HEAD -> master, tag: T1) C2
c11e156 C1
Reflog ...
Count ...
count: 6
size: 24
in-pack: 0
packs: 0
size-pack: 0
prune-packable: 0
garbage: 0
size-garbage: 0
Hashes ...
10bfa58a7bcbadfc6c9af616da89e4139c15fbb9
1abb34f82523039920fc629a68d3f82bc79acbd0
4b825dc642cb6eb9a060e54bf8d69288fbee4904
8aa22b5f0fed338dd13c16537c1c54b3496e3224
c11e1562835fe1e9c25bf293279bff0cf778b6e0
d1efc109115b00bac9d4e3d374a05a3df9754551
Теперь мы видим только два коммиты в настоящее время ссылаются на Git. Однако все шесть объектов все еще находятся в репозитории. Они останутся в хранилище до тех пор, пока они автоматически или явно не будут собраны мусор. Вы могли бы даже, например, оживить unreferated commit с git cherry-pick
или посмотреть на него с git show
. Пока же, давайте явно мусор собирать неопубликованные объекты и посмотреть, что Git делает за кулисами.
GIT_TRACE=1 git gc --aggressive --prune=now
Это будет выводить немного информации.
11:03:03.123194 git.c:348 trace: built-in: git 'gc' '--aggressive' '--prune=now'
11:03:03.123625 run-command.c:347 trace: run_command: 'pack-refs' '--all' '--prune'
11:03:03.124038 exec_cmd.c:129 trace: exec: 'git' 'pack-refs' '--all' '--prune'
11:03:03.126895 git.c:348 trace: built-in: git 'pack-refs' '--all' '--prune'
11:03:03.128298 run-command.c:347 trace: run_command: 'reflog' 'expire' '--all'
11:03:03.128635 exec_cmd.c:129 trace: exec: 'git' 'reflog' 'expire' '--all'
11:03:03.131322 git.c:348 trace: built-in: git 'reflog' 'expire' '--all'
11:03:03.133179 run-command.c:347 trace: run_command: 'repack' '-d' '-l' '-f' '--depth=250' '--window=250' '-a'
11:03:03.133522 exec_cmd.c:129 trace: exec: 'git' 'repack' '-d' '-l' '-f' '--depth=250' '--window=250' '-a'
11:03:03.136915 git.c:348 trace: built-in: git 'repack' '-d' '-l' '-f' '--depth=250' '--window=250' '-a'
11:03:03.137179 run-command.c:347 trace: run_command: 'pack-objects' '--keep-true-parents' '--honor-pack-keep' '--non-empty' '--all' '--reflog' '--indexed-objects' '--window=250' '--depth=250' '--no-reuse-delta' '--local' '--delta-base-offset' '.git/objects/pack/.tmp-8973-pack'
11:03:03.137686 exec_cmd.c:129 trace: exec: 'git' 'pack-objects' '--keep-true-parents' '--honor-pack-keep' '--non-empty' '--all' '--reflog' '--indexed-objects' '--window=250' '--depth=250' '--no-reuse-delta' '--local' '--delta-base-offset' '.git/objects/pack/.tmp-8973-pack'
11:03:03.140367 git.c:348 trace: built-in: git 'pack-objects' '--keep-true-parents' '--honor-pack-keep' '--non-empty' '--all' '--reflog' '--indexed-objects' '--window=250' '--depth=250' '--no-reuse-delta' '--local' '--delta-base-offset' '.git/objects/pack/.tmp-8973-pack'
Counting objects: 3, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), done.
Total 3 (delta 1), reused 0 (delta 0)
11:03:03.153843 run-command.c:347 trace: run_command: 'prune' '--expire' 'now'
11:03:03.154255 exec_cmd.c:129 trace: exec: 'git' 'prune' '--expire' 'now'
11:03:03.156744 git.c:348 trace: built-in: git 'prune' '--expire' 'now'
11:03:03.159210 run-command.c:347 trace: run_command: 'rerere' 'gc'
11:03:03.159527 exec_cmd.c:129 trace: exec: 'git' 'rerere' 'gc'
11:03:03.161807 git.c:348 trace: built-in: git 'rerere' 'gc'
И, наконец, давайте посмотрим на объекты.
git_log_objects
Какие выходы:
Log ...
10bfa58 (HEAD -> master, tag: T1) C2
c11e156 C1
Reflog ...
Count ...
count: 0
size: 0
in-pack: 3
packs: 1
size-pack: 1
prune-packable: 0
garbage: 0
size-garbage: 0
Hashes ...
10bfa58a7bcbadfc6c9af616da89e4139c15fbb9
4b825dc642cb6eb9a060e54bf8d69288fbee4904
c11e1562835fe1e9c25bf293279bff0cf778b6e0
Теперь мы видим, у нас есть только три объекта: два фиксаций и одно пустое дерево.
Этот ответ * удивительный *, есть еще несколько вещей, которые я не знал, например '-allow-empty'. – BanksySan
Хорошо, спасибо! – Peddipaga