Skip to content

Commit f0679f4

Browse files
author
Junio C Hamano
committed
Merge branch 'sp/reflog'
* sp/reflog: fetch.c: do not pass uninitialized lock to unlock_ref(). Test that git-branch -l works. Verify git-commit provides a reflog message. Enable ref log creation in git checkout -b. Create/delete branch ref logs. Include ref log detail in commit, reset, etc. Change order of -m option to update-ref. Correct force_write bug in refs.c Change 'master@noon' syntax to 'master@{noon}'. Log ref updates made by fetch. Force writing ref if it doesn't exist. Added logs/ directory to repository layout. General ref log reading improvements. Fix ref log parsing so it works properly. Support 'master@2 hours ago' syntax Log ref updates to logs/refs/<ref> Convert update-ref to use ref_lock API. Improve abstraction of ref lock/write.
2 parents 731651f + 99bd0f5 commit f0679f4

26 files changed

+755
-242
lines changed

Documentation/config.txt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,14 @@ core.preferSymlinkRefs::
7070
This is sometimes needed to work with old scripts that
7171
expect HEAD to be a symbolic link.
7272

73+
core.logAllRefUpdates::
74+
If true, `git-update-ref` will append a line to
75+
"$GIT_DIR/logs/<ref>" listing the new SHA1 and the date/time
76+
of the update. If the file does not exist it will be
77+
created automatically. This information can be used to
78+
determine what commit was the tip of a branch "2 days ago".
79+
This value is false by default (no logging).
80+
7381
core.repositoryFormatVersion::
7482
Internal variable identifying the repository format and layout
7583
version.

Documentation/git-branch.txt

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ SYNOPSIS
99
--------
1010
[verse]
1111
'git-branch' [-r]
12-
'git-branch' [-f] <branchname> [<start-point>]
12+
'git-branch' [-l] [-f] <branchname> [<start-point>]
1313
'git-branch' (-d | -D) <branchname>...
1414

1515
DESCRIPTION
@@ -23,7 +23,8 @@ If no <start-point> is given, the branch will be created with a head
2323
equal to that of the currently checked out branch.
2424

2525
With a `-d` or `-D` option, `<branchname>` will be deleted. You may
26-
specify more than one branch for deletion.
26+
specify more than one branch for deletion. If the branch currently
27+
has a ref log then the ref log will also be deleted.
2728

2829

2930
OPTIONS
@@ -34,6 +35,11 @@ OPTIONS
3435
-D::
3536
Delete a branch irrespective of its index status.
3637

38+
-l::
39+
Create the branch's ref log. This activates recording of
40+
all changes to made the branch ref, enabling use of date
41+
based sha1 expressions such as "<branchname>@{yesterday}".
42+
3743
-f::
3844
Force the creation of a new branch even if it means deleting
3945
a branch that already exists with the same name.

Documentation/git-checkout.txt

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ git-checkout - Checkout and switch to a branch
88
SYNOPSIS
99
--------
1010
[verse]
11-
'git-checkout' [-f] [-b <new_branch>] [-m] [<branch>]
11+
'git-checkout' [-f] [-b <new_branch> [-l]] [-m] [<branch>]
1212
'git-checkout' [-m] [<branch>] <paths>...
1313

1414
DESCRIPTION
@@ -40,6 +40,11 @@ OPTIONS
4040
by gitlink:git-check-ref-format[1]. Some of these checks
4141
may restrict the characters allowed in a branch name.
4242

43+
-l::
44+
Create the new branch's ref log. This activates recording of
45+
all changes to made the branch ref, enabling use of date
46+
based sha1 expressions such as "<branchname>@{yesterday}".
47+
4348
-m::
4449
If you have local modifications to one or more files that
4550
are different between the current branch and the branch to

Documentation/git-rev-parse.txt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,13 @@ syntax.
124124
happen to have both heads/master and tags/master, you can
125125
explicitly say 'heads/master' to tell git which one you mean.
126126

127+
* A suffix '@' followed by a date specification enclosed in a brace
128+
pair (e.g. '\{yesterday\}', '\{1 month 2 weeks 3 days 1 hour 1
129+
second ago\}' or '\{1979-02-26 18:30:00\}') to specify the value
130+
of the ref at a prior point in time. This suffix may only be
131+
used immediately following a ref name and the ref must have an
132+
existing log ($GIT_DIR/logs/<ref>).
133+
127134
* A suffix '{caret}' to a revision parameter means the first parent of
128135
that commit object. '{caret}<n>' means the <n>th parent (i.e.
129136
'rev{caret}'

Documentation/git-update-ref.txt

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ git-update-ref - update the object name stored in a ref safely
77

88
SYNOPSIS
99
--------
10-
'git-update-ref' <ref> <newvalue> [<oldvalue>]
10+
'git-update-ref' [-m <reason>] <ref> <newvalue> [<oldvalue>]
1111

1212
DESCRIPTION
1313
-----------
@@ -49,6 +49,32 @@ for reading but not for writing (so we'll never write through a
4949
ref symlink to some other tree, if you have copied a whole
5050
archive by creating a symlink tree).
5151

52+
Logging Updates
53+
---------------
54+
If config parameter "core.logAllRefUpdates" is true or the file
55+
"$GIT_DIR/logs/<ref>" exists then `git-update-ref` will append
56+
a line to the log file "$GIT_DIR/logs/<ref>" (dereferencing all
57+
symbolic refs before creating the log name) describing the change
58+
in ref value. Log lines are formatted as:
59+
60+
. oldsha1 SP newsha1 SP committer LF
61+
+
62+
Where "oldsha1" is the 40 character hexadecimal value previously
63+
stored in <ref>, "newsha1" is the 40 character hexadecimal value of
64+
<newvalue> and "committer" is the committer's name, email address
65+
and date in the standard GIT committer ident format.
66+
67+
Optionally with -m:
68+
69+
. oldsha1 SP newsha1 SP committer TAB message LF
70+
+
71+
Where all fields are as described above and "message" is the
72+
value supplied to the -m option.
73+
74+
An update will fail (without changing <ref>) if the current user is
75+
unable to create a new log file, append to the existing log file
76+
or does not have committer information available.
77+
5278
Author
5379
------
5480
Written by Linus Torvalds <[email protected]>.

Documentation/repository-layout.txt

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,3 +128,14 @@ remotes::
128128
Stores shorthands to be used to give URL and default
129129
refnames to interact with remote repository to `git
130130
fetch`, `git pull` and `git push` commands.
131+
132+
logs::
133+
Records of changes made to refs are stored in this
134+
directory. See the documentation on git-update-ref
135+
for more information.
136+
137+
logs/refs/heads/`name`::
138+
Records all changes made to the branch tip named `name`.
139+
140+
logs/refs/tags/`name`::
141+
Records all changes made to the tag named `name`.

cache.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,7 @@ extern void rollback_index_file(struct cache_file *);
179179
extern int trust_executable_bit;
180180
extern int assume_unchanged;
181181
extern int prefer_symlink_refs;
182+
extern int log_all_ref_updates;
182183
extern int warn_ambiguous_refs;
183184
extern int diff_rename_limit_default;
184185
extern int shared_repository;

config.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,11 @@ int git_default_config(const char *var, const char *value)
269269
return 0;
270270
}
271271

272+
if (!strcmp(var, "core.logallrefupdates")) {
273+
log_all_ref_updates = git_config_bool(var, value);
274+
return 0;
275+
}
276+
272277
if (!strcmp(var, "core.warnambiguousrefs")) {
273278
warn_ambiguous_refs = git_config_bool(var, value);
274279
return 0;

environment.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ char git_default_name[MAX_GITNAME];
1414
int trust_executable_bit = 1;
1515
int assume_unchanged = 0;
1616
int prefer_symlink_refs = 0;
17+
int log_all_ref_updates = 0;
1718
int warn_ambiguous_refs = 1;
1819
int repository_format_version = 0;
1920
char git_commit_encoding[MAX_ENCODING_LENGTH] = "utf-8";

fetch.c

Lines changed: 37 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include "refs.h"
99

1010
const char *write_ref = NULL;
11+
const char *write_ref_log_details = NULL;
1112

1213
int get_tree = 0;
1314
int get_history = 0;
@@ -202,23 +203,51 @@ static int mark_complete(const char *path, const unsigned char *sha1)
202203

203204
int pull(char *target)
204205
{
206+
struct ref_lock *lock = NULL;
205207
unsigned char sha1[20];
208+
char *msg;
209+
int ret;
206210

207211
save_commit_buffer = 0;
208212
track_object_refs = 0;
213+
if (write_ref) {
214+
lock = lock_ref_sha1(write_ref, NULL, 0);
215+
if (!lock) {
216+
error("Can't lock ref %s", write_ref);
217+
return -1;
218+
}
219+
}
209220

210221
if (!get_recover)
211222
for_each_ref(mark_complete);
212223

213-
if (interpret_target(target, sha1))
214-
return error("Could not interpret %s as something to pull",
215-
target);
216-
if (process(lookup_unknown_object(sha1)))
224+
if (interpret_target(target, sha1)) {
225+
error("Could not interpret %s as something to pull", target);
226+
if (lock)
227+
unlock_ref(lock);
217228
return -1;
218-
if (loop())
229+
}
230+
if (process(lookup_unknown_object(sha1))) {
231+
if (lock)
232+
unlock_ref(lock);
219233
return -1;
220-
221-
if (write_ref)
222-
write_ref_sha1_unlocked(write_ref, sha1);
234+
}
235+
if (loop()) {
236+
if (lock)
237+
unlock_ref(lock);
238+
return -1;
239+
}
240+
241+
if (write_ref) {
242+
if (write_ref_log_details) {
243+
msg = xmalloc(strlen(write_ref_log_details) + 12);
244+
sprintf(msg, "fetch from %s", write_ref_log_details);
245+
} else
246+
msg = NULL;
247+
ret = write_ref_sha1(lock, sha1, msg ? msg : "fetch (unknown)");
248+
if (msg)
249+
free(msg);
250+
return ret;
251+
}
223252
return 0;
224253
}

fetch.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,9 @@ extern int fetch_ref(char *ref, unsigned char *sha1);
2525
/* If set, the ref filename to write the target value to. */
2626
extern const char *write_ref;
2727

28+
/* If set additional text will appear in the ref log. */
29+
extern const char *write_ref_log_details;
30+
2831
/* Set to fetch the target tree. */
2932
extern int get_tree;
3033

git-am.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -413,7 +413,7 @@ do
413413
parent=$(git-rev-parse --verify HEAD) &&
414414
commit=$(git-commit-tree $tree -p $parent <"$dotest/final-commit") &&
415415
echo Committed: $commit &&
416-
git-update-ref HEAD $commit $parent ||
416+
git-update-ref -m "am: $SUBJECT" HEAD $commit $parent ||
417417
stop_here $this
418418

419419
if test -x "$GIT_DIR"/hooks/post-applypatch

git-applypatch.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -204,7 +204,7 @@ echo Wrote tree $tree
204204
parent=$(git-rev-parse --verify HEAD) &&
205205
commit=$(git-commit-tree $tree -p $parent <"$final") || exit 1
206206
echo Committed: $commit
207-
git-update-ref HEAD $commit $parent || exit
207+
git-update-ref -m "applypatch: $SUBJECT" HEAD $commit $parent || exit
208208

209209
if test -x "$GIT_DIR"/hooks/post-applypatch
210210
then

git-branch.sh

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
#!/bin/sh
22

3-
USAGE='[(-d | -D) <branchname>] | [[-f] <branchname> [<start-point>]] | -r'
3+
USAGE='[-l] [(-d | -D) <branchname>] | [[-f] <branchname> [<start-point>]] | -r'
44
LONG_USAGE='If no arguments, show available branches and mark current branch with a star.
55
If one argument, create a new branch <branchname> based off of current HEAD.
66
If two arguments, create a new branch <branchname> based off of <start-point>.'
@@ -42,6 +42,7 @@ If you are sure you want to delete it, run 'git branch -D $branch_name'."
4242
esac
4343
;;
4444
esac
45+
rm -f "$GIT_DIR/logs/refs/heads/$branch_name"
4546
rm -f "$GIT_DIR/refs/heads/$branch_name"
4647
echo "Deleted branch $branch_name."
4748
done
@@ -55,6 +56,7 @@ ls_remote_branches () {
5556
}
5657

5758
force=
59+
create_log=
5860
while case "$#,$1" in 0,*) break ;; *,-*) ;; *) break ;; esac
5961
do
6062
case "$1" in
@@ -69,6 +71,9 @@ do
6971
-f)
7072
force="$1"
7173
;;
74+
-l)
75+
create_log="yes"
76+
;;
7277
--)
7378
shift
7479
break
@@ -117,4 +122,9 @@ then
117122
die "cannot force-update the current branch."
118123
fi
119124
fi
120-
git update-ref "refs/heads/$branchname" $rev
125+
if test "$create_log" = 'yes'
126+
then
127+
mkdir -p $(dirname "$GIT_DIR/logs/refs/heads/$branchname")
128+
touch "$GIT_DIR/logs/refs/heads/$branchname"
129+
fi
130+
git update-ref -m "branch: Created from $head" "refs/heads/$branchname" $rev

git-checkout.sh

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,13 @@ SUBDIRECTORY_OK=Sometimes
55
. git-sh-setup
66

77
old=$(git-rev-parse HEAD)
8+
old_name=HEAD
89
new=
10+
new_name=
911
force=
1012
branch=
1113
newbranch=
14+
newbranch_log=
1215
merge=
1316
while [ "$#" != "0" ]; do
1417
arg="$1"
@@ -24,6 +27,9 @@ while [ "$#" != "0" ]; do
2427
git-check-ref-format "heads/$newbranch" ||
2528
die "git checkout: we do not like '$newbranch' as a branch name."
2629
;;
30+
"-l")
31+
newbranch_log=1
32+
;;
2733
"-f")
2834
force=1
2935
;;
@@ -44,16 +50,19 @@ while [ "$#" != "0" ]; do
4450
exit 1
4551
fi
4652
new="$rev"
53+
new_name="$arg^0"
4754
if [ -f "$GIT_DIR/refs/heads/$arg" ]; then
4855
branch="$arg"
4956
fi
5057
elif rev=$(git-rev-parse --verify "$arg^{tree}" 2>/dev/null)
5158
then
5259
# checking out selected paths from a tree-ish.
5360
new="$rev"
61+
new_name="$arg^{tree}"
5462
branch=
5563
else
5664
new=
65+
new_name=
5766
branch=
5867
set x "$arg" "$@"
5968
shift
@@ -114,7 +123,7 @@ then
114123
cd "$cdup"
115124
fi
116125

117-
[ -z "$new" ] && new=$old
126+
[ -z "$new" ] && new=$old && new_name="$old_name"
118127

119128
# If we don't have an old branch that we're switching to,
120129
# and we don't have a new branch name for the target we
@@ -187,9 +196,11 @@ fi
187196
#
188197
if [ "$?" -eq 0 ]; then
189198
if [ "$newbranch" ]; then
190-
leading=`expr "refs/heads/$newbranch" : '\(.*\)/'` &&
191-
mkdir -p "$GIT_DIR/$leading" &&
192-
echo $new >"$GIT_DIR/refs/heads/$newbranch" || exit
199+
if [ "$newbranch_log" ]; then
200+
mkdir -p $(dirname "$GIT_DIR/logs/refs/heads/$newbranch")
201+
touch "$GIT_DIR/logs/refs/heads/$newbranch"
202+
fi
203+
git-update-ref -m "checkout: Created from $new_name" "refs/heads/$newbranch" $new || exit
193204
branch="$newbranch"
194205
fi
195206
[ "$branch" ] &&

git-commit.sh

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -713,7 +713,8 @@ then
713713
rm -f "$TMP_INDEX"
714714
fi &&
715715
commit=$(cat "$GIT_DIR"/COMMIT_MSG | git-commit-tree $tree $PARENTS) &&
716-
git-update-ref HEAD $commit $current &&
716+
rlogm=$(sed -e 1q "$GIT_DIR"/COMMIT_MSG) &&
717+
git-update-ref -m "commit: $rlogm" HEAD $commit $current &&
717718
rm -f -- "$GIT_DIR/MERGE_HEAD" &&
718719
if test -f "$NEXT_INDEX"
719720
then

git-reset.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ then
4848
else
4949
rm -f "$GIT_DIR/ORIG_HEAD"
5050
fi
51-
git-update-ref HEAD "$rev"
51+
git-update-ref -m "reset $reset_type $@" HEAD "$rev"
5252

5353
case "$reset_type" in
5454
--hard )

0 commit comments

Comments
 (0)