зеркало из https://github.com/microsoft/git.git
Merge branch 'jc/maint-no-reflog-expire-unreach-for-head'
* jc/maint-no-reflog-expire-unreach-for-head: reflog --expire-unreachable: special case entries in "HEAD" reflog more war on "sleep" in tests Document gc.<pattern>.reflogexpire variables Conflicts: Documentation/config.txt
This commit is contained in:
Коммит
a660534e06
|
@ -946,13 +946,19 @@ gc.pruneexpire::
|
|||
unreachable objects immediately.
|
||||
|
||||
gc.reflogexpire::
|
||||
gc.<pattern>.reflogexpire::
|
||||
'git reflog expire' removes reflog entries older than
|
||||
this time; defaults to 90 days.
|
||||
this time; defaults to 90 days. With "<pattern>" (e.g.
|
||||
"refs/stash") in the middle the setting applies only to
|
||||
the refs that match the <pattern>.
|
||||
|
||||
gc.reflogexpireunreachable::
|
||||
gc.<ref>.reflogexpireunreachable::
|
||||
'git reflog expire' removes reflog entries older than
|
||||
this time and are not reachable from the current tip;
|
||||
defaults to 30 days.
|
||||
defaults to 30 days. With "<pattern>" (e.g. "refs/stash")
|
||||
in the middle, the setting applies only to the refs that
|
||||
match the <pattern>.
|
||||
|
||||
gc.rerereresolved::
|
||||
Records of conflicted merge you resolved earlier are
|
||||
|
|
|
@ -88,6 +88,16 @@ commits prior to the amend or rebase occurring. Since these changes
|
|||
are not part of the current project most users will want to expire
|
||||
them sooner. This option defaults to '30 days'.
|
||||
|
||||
The above two configuration variables can be given to a pattern. For
|
||||
example, this sets non-default expiry values only to remote tracking
|
||||
branches:
|
||||
|
||||
------------
|
||||
[gc "refs/remotes/*"]
|
||||
reflogExpire = never
|
||||
reflogexpireUnreachable = 3 days
|
||||
------------
|
||||
|
||||
The optional configuration variable 'gc.rerereresolved' indicates
|
||||
how long records of conflicted merge you resolved earlier are
|
||||
kept. This defaults to 60 days.
|
||||
|
|
|
@ -34,8 +34,11 @@ struct cmd_reflog_expire_cb {
|
|||
|
||||
struct expire_reflog_cb {
|
||||
FILE *newlog;
|
||||
const char *ref;
|
||||
struct commit *ref_commit;
|
||||
enum {
|
||||
UE_NORMAL,
|
||||
UE_ALWAYS,
|
||||
UE_HEAD
|
||||
} unreachable_expire_kind;
|
||||
struct commit_list *mark_list;
|
||||
unsigned long mark_limit;
|
||||
struct cmd_reflog_expire_cb *cmd;
|
||||
|
@ -305,7 +308,7 @@ static int expire_reflog_ent(unsigned char *osha1, unsigned char *nsha1,
|
|||
goto prune;
|
||||
|
||||
if (timestamp < cb->cmd->expire_unreachable) {
|
||||
if (!cb->ref_commit)
|
||||
if (cb->unreachable_expire_kind == UE_ALWAYS)
|
||||
goto prune;
|
||||
if (unreachable(cb, old, osha1) || unreachable(cb, new, nsha1))
|
||||
goto prune;
|
||||
|
@ -332,12 +335,27 @@ static int expire_reflog_ent(unsigned char *osha1, unsigned char *nsha1,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int push_tip_to_list(const char *refname, const unsigned char *sha1, int flags, void *cb_data)
|
||||
{
|
||||
struct commit_list **list = cb_data;
|
||||
struct commit *tip_commit;
|
||||
if (flags & REF_ISSYMREF)
|
||||
return 0;
|
||||
tip_commit = lookup_commit_reference_gently(sha1, 1);
|
||||
if (!tip_commit)
|
||||
return 0;
|
||||
commit_list_insert(tip_commit, list);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int expire_reflog(const char *ref, const unsigned char *sha1, int unused, void *cb_data)
|
||||
{
|
||||
struct cmd_reflog_expire_cb *cmd = cb_data;
|
||||
struct expire_reflog_cb cb;
|
||||
struct ref_lock *lock;
|
||||
char *log_file, *newlog_path = NULL;
|
||||
struct commit *tip_commit;
|
||||
struct commit_list *tips;
|
||||
int status = 0;
|
||||
|
||||
memset(&cb, 0, sizeof(cb));
|
||||
|
@ -357,18 +375,49 @@ static int expire_reflog(const char *ref, const unsigned char *sha1, int unused,
|
|||
cb.newlog = fopen(newlog_path, "w");
|
||||
}
|
||||
|
||||
cb.ref_commit = lookup_commit_reference_gently(sha1, 1);
|
||||
cb.ref = ref;
|
||||
cb.cmd = cmd;
|
||||
if (cb.ref_commit) {
|
||||
cb.mark_list = NULL;
|
||||
commit_list_insert(cb.ref_commit, &cb.mark_list);
|
||||
|
||||
if (!cmd->expire_unreachable || !strcmp(ref, "HEAD")) {
|
||||
tip_commit = NULL;
|
||||
cb.unreachable_expire_kind = UE_HEAD;
|
||||
} else {
|
||||
tip_commit = lookup_commit_reference_gently(sha1, 1);
|
||||
if (!tip_commit)
|
||||
cb.unreachable_expire_kind = UE_ALWAYS;
|
||||
else
|
||||
cb.unreachable_expire_kind = UE_NORMAL;
|
||||
}
|
||||
|
||||
if (cmd->expire_unreachable <= cmd->expire_total)
|
||||
cb.unreachable_expire_kind = UE_ALWAYS;
|
||||
|
||||
cb.mark_list = NULL;
|
||||
tips = NULL;
|
||||
if (cb.unreachable_expire_kind != UE_ALWAYS) {
|
||||
if (cb.unreachable_expire_kind == UE_HEAD) {
|
||||
struct commit_list *elem;
|
||||
for_each_ref(push_tip_to_list, &tips);
|
||||
for (elem = tips; elem; elem = elem->next)
|
||||
commit_list_insert(elem->item, &cb.mark_list);
|
||||
} else {
|
||||
commit_list_insert(tip_commit, &cb.mark_list);
|
||||
}
|
||||
cb.mark_limit = cmd->expire_total;
|
||||
mark_reachable(&cb);
|
||||
}
|
||||
|
||||
for_each_reflog_ent(ref, expire_reflog_ent, &cb);
|
||||
if (cb.ref_commit)
|
||||
clear_commit_marks(cb.ref_commit, REACHABLE);
|
||||
|
||||
if (cb.unreachable_expire_kind != UE_ALWAYS) {
|
||||
if (cb.unreachable_expire_kind == UE_HEAD) {
|
||||
struct commit_list *elem;
|
||||
for (elem = tips; elem; elem = elem->next)
|
||||
clear_commit_marks(tip_commit, REACHABLE);
|
||||
free_commit_list(tips);
|
||||
} else {
|
||||
clear_commit_marks(tip_commit, REACHABLE);
|
||||
}
|
||||
}
|
||||
finish:
|
||||
if (cb.newlog) {
|
||||
if (fclose(cb.newlog)) {
|
||||
|
|
|
@ -8,6 +8,7 @@ test_expect_success 'objects in packs marked .keep are not repacked' '
|
|||
echo content1 > file1 &&
|
||||
echo content2 > file2 &&
|
||||
git add . &&
|
||||
test_tick &&
|
||||
git commit -m initial_commit &&
|
||||
# Create two packs
|
||||
# The first pack will contain all of the objects except one
|
||||
|
@ -40,6 +41,7 @@ test_expect_success 'loose objects in alternate ODB are not repacked' '
|
|||
echo content3 > file3 &&
|
||||
objsha1=$(GIT_OBJECT_DIRECTORY=alt_objects git hash-object -w file3) &&
|
||||
git add file3 &&
|
||||
test_tick &&
|
||||
git commit -m commit_file3 &&
|
||||
git repack -a -d -l &&
|
||||
git prune-packed &&
|
||||
|
@ -73,6 +75,7 @@ test_expect_success 'packed obs in alt ODB are repacked when local repo has pack
|
|||
rm -f .git/objects/pack/* &&
|
||||
echo new_content >> file1 &&
|
||||
git add file1 &&
|
||||
test_tick &&
|
||||
git commit -m more_content &&
|
||||
git repack &&
|
||||
git repack -a -d &&
|
||||
|
@ -118,8 +121,8 @@ test_expect_success 'packed unreachable obs in alternate ODB are not loosened' '
|
|||
mv .git/objects/pack/* alt_objects/pack/ &&
|
||||
csha1=$(git rev-parse HEAD^{commit}) &&
|
||||
git reset --hard HEAD^ &&
|
||||
sleep 1 &&
|
||||
git reflog expire --expire=now --expire-unreachable=now --all &&
|
||||
test_tick &&
|
||||
git reflog expire --expire=$test_tick --expire-unreachable=$test_tick --all &&
|
||||
# The pack-objects call on the next line is equivalent to
|
||||
# git repack -A -d without the call to prune-packed
|
||||
git pack-objects --honor-pack-keep --non-empty --all --reflog \
|
||||
|
@ -156,7 +159,7 @@ test_expect_success 'objects made unreachable by grafts only are kept' '
|
|||
H1=$(git rev-parse HEAD^) &&
|
||||
H2=$(git rev-parse HEAD^^) &&
|
||||
echo "$H0 $H2" > .git/info/grafts &&
|
||||
git reflog expire --expire=now --expire-unreachable=now --all &&
|
||||
git reflog expire --expire=$test_tick --expire-unreachable=$test_tick --all &&
|
||||
git repack -a -d &&
|
||||
git cat-file -t $H1
|
||||
'
|
||||
|
|
|
@ -11,17 +11,20 @@ tsha1=
|
|||
test_expect_success '-A with -d option leaves unreachable objects unpacked' '
|
||||
echo content > file1 &&
|
||||
git add . &&
|
||||
test_tick &&
|
||||
git commit -m initial_commit &&
|
||||
# create a transient branch with unique content
|
||||
git checkout -b transient_branch &&
|
||||
echo more content >> file1 &&
|
||||
# record the objects created in the database for file, commit, tree
|
||||
fsha1=$(git hash-object file1) &&
|
||||
test_tick &&
|
||||
git commit -a -m more_content &&
|
||||
csha1=$(git rev-parse HEAD^{commit}) &&
|
||||
tsha1=$(git rev-parse HEAD^{tree}) &&
|
||||
git checkout master &&
|
||||
echo even more content >> file1 &&
|
||||
test_tick &&
|
||||
git commit -a -m even_more_content &&
|
||||
# delete the transient branch
|
||||
git branch -D transient_branch &&
|
||||
|
@ -34,9 +37,11 @@ test_expect_success '-A with -d option leaves unreachable objects unpacked' '
|
|||
git show $fsha1 &&
|
||||
git show $csha1 &&
|
||||
git show $tsha1 &&
|
||||
# now expire the reflog
|
||||
sleep 1 &&
|
||||
git reflog expire --expire-unreachable=now --all &&
|
||||
# now expire the reflog, while keeping reachable ones but expiring
|
||||
# unreachables immediately
|
||||
test_tick &&
|
||||
sometimeago=$(( $test_tick - 10000 )) &&
|
||||
git reflog expire --expire=$sometimeago --expire-unreachable=$test_tick --all &&
|
||||
# and repack
|
||||
git repack -A -d -l &&
|
||||
# verify objects are retained unpacked
|
||||
|
@ -71,7 +76,7 @@ test_expect_success '-A without -d option leaves unreachable objects packed' '
|
|||
test 1 = $(ls -1 .git/objects/pack/pack-*.pack | wc -l) &&
|
||||
packfile=$(ls .git/objects/pack/pack-*.pack) &&
|
||||
git branch -D transient_branch &&
|
||||
sleep 1 &&
|
||||
test_tick &&
|
||||
git repack -A -l &&
|
||||
test ! -f "$fsha1path" &&
|
||||
test ! -f "$csha1path" &&
|
||||
|
|
Загрузка…
Ссылка в новой задаче