Краткий ответ: коммиты C3
и C4
останутся в базе данных объектов Git до тех пор, пока они не будут удалены сборщиком мусора.
Длинный ответ: сборка мусора будет происходить автоматически с помощью различных команд Git фарфора или при явной сборке мусора. Существует много сценариев, которые могут вызвать автоматическую сборку мусора; взгляните на gc.*
параметры конфигурации, чтобы получить представление. Вы можете явно собирать мусор с помощью git gc
встроенной команды. Давайте посмотрим на пример, чтобы увидеть, что происходит.
Во-первых, давайте настроим нашу среду (я использую 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/master@{0}: commit: C5
1abb34f refs/heads/master@{1}: commit: C4
8aa22b5 refs/heads/master@{2}: commit: C3
10bfa58 refs/heads/master@{3}: commit: C2
c11e156 refs/heads/master@{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 есть ссылки на ветки, теги и/или журналы ссылок на все пять объектов коммитов. Пока 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 ссылается только на два коммита. Однако все шесть объектов все еще находятся в репозитории. Они останутся в репозитории до тех пор, пока не будут автоматически или явно удалены сборщиком мусора. Вы даже можете, например, оживить фиксацию без ссылок с помощью 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
Теперь мы видим, что у нас есть только три объекта: два коммита и одно пустое дерево.
person
Dan Cruz
schedule
07.05.2015