Git 孤儿犯怎么办?
我有一份包含四项承诺的回购协议:Git 孤儿犯怎么办?,git,git-commit,git-reset,Git,Git Commit,Git Reset,我有一份包含四项承诺的回购协议: $ git log --oneline --decorate 6c35831 (HEAD, master) C4 974073b C3 e27b22c C2 9f2d694 C1 我reset--soft到C2提交,现在我有一个这样的回购协议: $ git reset e27b22c --soft $ git log --oneline --decorate e27b22c (HEAD, master) C2 9f2d694 C1 现在,我添加了一个额外的
$ git log --oneline --decorate
6c35831 (HEAD, master) C4
974073b C3
e27b22c C2
9f2d694 C1
我reset--soft
到C2
提交,现在我有一个这样的回购协议:
$ git reset e27b22c --soft
$ git log --oneline --decorate
e27b22c (HEAD, master) C2
9f2d694 C1
现在,我添加了一个额外的提交,因此日志如下所示:
$ git log --oneline --decorate
545fa99 (HEAD, master) C5
e27b22c C2
9f2d694 C1
提交
C3
和C4
时发生了什么?我没有删除它们,所以我假设它们仍然存在,C3
的父级仍然是C2
孤立的提交只需停留在那里,直到它们通过显式运行git gc
进行垃圾收集,然后运行git show 6c35831
查看C4是否仍然存在。运行git reflog master
查看master
用于引用的内容(很多)。其中一个条目(master^{1}
最有可能,但如果您进行了其他更改,则可能是一个较早的条目)应该对应于6c35831
,并且git show master^{1}
(或任何条目)应该显示与我提到的第一个git show
命令相同的输出。简短回答:提交C3
和C4
将保留在git对象数据库中,直到它们被垃圾回收
详细回答:垃圾收集将通过不同的Git命令自动发生,或者在显式垃圾收集时发生。有许多场景可能触发自动垃圾回收;看一看图片,想一想。您可以使用。让我们看一个例子,看看会发生什么
首先,让我们设置我们的环境(我正在使用Linux;对您的环境进行必要的更改),以便在不同的Git存储库中获得相同的对象哈希
export GIT_AUTHOR_NAME='Wile E. Coyote'
export GIT_AUTHOR_EMAIL=coyote@acme.com
export GIT_AUTHOR_DATE=2015-01-01T12:00:00
export GIT_COMMITTER_NAME='Roadrunner'
export GIT_COMMITTER_EMAIL=roadrunner@acme.com
export GIT_COMMITTER_DATE=2015-01-01T12:00:00
由于提交对象散列是使用此信息生成的,因此如果我们使用相同的author和committer值,我们现在都应该得到相同的散列
现在,让我们初始化一个函数,使用、和记录对象信息
现在让我们初始化一个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
git_log_objects
这给了我以下输出:
[master (root-commit) c11e156] C1
Author: Wile E. Coyote <coyote@acme.com>
[master 10bfa58] C2
Author: Wile E. Coyote <coyote@acme.com>
[master 8aa22b5] C3
Author: Wile E. Coyote <coyote@acme.com>
[master 1abb34f] C4
Author: Wile E. Coyote <coyote@acme.com>
[master d1efc10] C5
Author: Wile E. Coyote <coyote@acme.com>
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
哪些产出:
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
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
现在我们看到Git只引用了两个提交。但是,所有六个对象仍在存储库中。它们将保留在存储库中,直到它们被自动或显式地垃圾回收。例如,您甚至可以使用或查看未引用的提交。不过现在,让我们显式地对未引用的对象进行垃圾收集,看看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 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
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
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
现在我们看到只有三个对象:两个提交和一个空树。接下来的问题。我是否更改了历史记录或只是添加了历史记录?就分支中的内容而言(即,
git log
),您已经更改了历史记录。就回购协议(即,git reflog
)中发生的事情而言,您添加了它。因此,如果这些提交被发布,这会是一件“坏事”吗?您通常会发布一个分支,因此它们不会被包括在内。不过,重置公共分支通常被认为是一种不好的做法——它会迫使所有在其上重新设置基础的人强制更新其本地分支。这个答案太棒了,还有一些我不知道的事情,比如——allow empty
。