Câu trả lời ngắn: Cam kết C3
và C4
sẽ vẫn còn trong cơ sở dữ liệu đối tượng Git cho đến khi chúng được thu thập rác.
Câu trả lời dài: Việc thu gom rác sẽ tự động diễn ra bằng các lệnh sứ Git khác nhau hoặc khi thu gom rác một cách rõ ràng. Có rất nhiều kịch bản có thể kích hoạt một bộ sưu tập rác tự động; hãy xem gc.*
configuration settings để có ý tưởng. Bạn có thể kiếm tiền một cách rõ ràng bằng cách sử dụng git gc
builtin command. Hãy xem một ví dụ để xem điều gì xảy ra.
Trước tiên, hãy thiết lập môi trường của chúng tôi (tôi đang sử dụng Linux; thực hiện thay đổi khi cần thiết cho môi trường của bạn).
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
Kể từ khi băm đối tượng cam kết được tạo bằng cách sử dụng cùng một giá trị tác giả và giá trị, tất cả chúng ta đều có cùng một giá trị băm.
Bây giờ chúng ta hãy khởi tạo một chức năng để đăng nhập thông tin đối tượng sử dụng git log
, git reflog
, git count-objects
, git rev-list
và 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
}
Bây giờ chúng ta hãy khởi tạo một kho lưu trữ Git.
git --version
git init
git_log_objects
nào, đối với tôi, kết quả đầu ra:
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 ...
Đúng như dự đoán, chúng ta có một kho khởi tạo không có đối tượng trong đó. Hãy thực hiện một số cam kết và xem xét các đối tượng.
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
nào mang lại cho tôi kết quả như sau:
[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
Bây giờ chúng ta có sáu đối tượng trong kho: năm cam kết và một cây rỗng. Chúng ta có thể thấy Git có các tham chiếu branch, tag và/hoặc reflog cho tất cả năm đối tượng commit. Miễn là Git tham chiếu đến một đối tượng, đối tượng đó sẽ không được thu thập rác. Rõ ràng chạy một bộ sưu tập gabage sẽ dẫn đến không có đối tượng nào bị xóa khỏi kho lưu trữ. (Tôi sẽ để lại xác minh điều này như một bài tập cho bạn để hoàn thành.)
Bây giờ chúng ta hãy loại bỏ tài liệu tham khảo Git đến C3
, C4
và C5
cam kết.
git reset --soft T1
git reflog expire --expire=all --all
git_log_objects
Những kết quả đầu ra:
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
Bây giờ chúng ta thấy chỉ có hai cam kết đang được tham chiếu bởi Git. Tuy nhiên, tất cả sáu đối tượng vẫn còn trong kho. Chúng sẽ vẫn còn trong kho lưu trữ cho đến khi chúng được thu thập tự động hoặc một cách rõ ràng. Bạn thậm chí có thể, ví dụ, làm sống lại một cam kết không được chấp nhận với git cherry-pick
hoặc xem nó với git show
. Tuy nhiên, bây giờ, chúng ta hãy thu gom rác một cách rõ ràng các đối tượng không được quan tâm và xem Git làm gì đằng sau hậu trường.
GIT_TRACE=1 git gc --aggressive --prune=now
Điều này sẽ tạo ra một chút thông tin.
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'
Và cuối cùng, hãy nhìn vào các đối tượng.
git_log_objects
Những kết quả đầu ra:
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
Bây giờ chúng ta thấy chúng ta chỉ có ba đối tượng: hai cam kết và một cây rỗng.
Câu trả lời đó là * tuyệt vời *, có một số thứ khác mà tôi không biết ở đó, như '--allow-empty'. – BanksySan
Tốt nhất, cảm ơn bạn! – Peddipaga