* Re: Tracking branch history
From: Shawn Pearce @ 2006-05-13 18:18 UTC (permalink / raw)
To: Junio C Hamano; +Cc: Linus Torvalds, git
In-Reply-To: <7vbqu1vps3.fsf@assigned-by-dhcp.cox.net>
Junio C Hamano <junkio@cox.net> wrote:
> Linus Torvalds <torvalds@osdl.org> writes:
>
> > I actually disagree with Junio - I think the logging the name made sense.
> > If you have a shared repo with multiple people pushing to the same branch,
> > it's interesting to see who does the pushing.
>
> Yes, I agree recording that information is interesting.
>
> My comment was about how it is recorded. In the local case
> GIT_COMMITTER_IDENT is what you want as Shawn did in his
> original proposal, but remote "pushing into shared repository"
> case I do not think it is available in general.
>
> Well, at least that was what I was thinking when I made that
> comment. However,
>
> If the pushers arrange to have appropriate environment variables
> while receive-pack does its work (.git/config in the target
> repository is not an appropriate place to get user.* settings
> from in a shared setting), what you say makes perfect sense.
>
> Having the usual enviornment available would be handy to make
> the hooks on the receiving end to do useful things anyway, so I
> retract that suggestion.
>
> > I also think it might be good to save the oldsha1 value. Yes, it _should_
> > always be the previous sha1 logged, but it's interesting to see in case it
> > isn't (ie the ref was updated some other way), and it's also interesting
> > for the first entry after logging has been enabled.
> >
> > Linue
>
> Yes, and also what user-level command was used to cause update
> the ref; was it a merge from remote, own commit, rewind/rebase?
>
> Junia
>
> ;-)
>
New version of the patch below; this patch superceeds the prior two.
The format now includes the old sha1 and committer ident, and does
not write a log record if the update-ref is pointless.
Hmm, why does update-ref do a pointless update?
Now the problem with this patch is it doesn't append to the log
in the case of upload-pack or fetch; nor does it record what user
level command caused the update.
[spearce@pb15 git]$ grep update-ref *.sh *.perl *.py | wc -l
20
Hmm. That's easy enough to fix. Anyone up for a '-m foo' comment
switch to update-ref from the higher-level tools such that foo
appears as part of the log line?
I'll be offline for a few hours but can work on this some more
later tonight.
--> -
Log ref updates to logs/refs/<ref>
If config parameter core.logRefUpdates is true then append a line
to .git/logs/refs/<ref> whenever git-update-ref <ref> is executed.
Each log line contains the following information:
oldsha1 <SP> newsha1 <SP> committer <LF>
where committer is the current user, date, time and timezone in
the standard GIT ident format. If the caller is unable to append
to the log file then git-update-ref will fail without updating <ref>.
---
Documentation/config.txt | 7 ++++++
Documentation/git-update-ref.txt | 19 +++++++++++++++
cache.h | 1 +
config.c | 5 ++++
environment.c | 1 +
update-ref.c | 48 ++++++++++++++++++++++++++++++++++++--
6 files changed, 78 insertions(+), 3 deletions(-)
898e33d9c2def73296697d65dff0676d96adb5d8
diff --git a/Documentation/config.txt b/Documentation/config.txt
index d1a4bec..f06695c 100644
--- a/Documentation/config.txt
+++ b/Documentation/config.txt
@@ -70,6 +70,13 @@ core.preferSymlinkRefs::
This is sometimes needed to work with old scripts that
expect HEAD to be a symbolic link.
+core.logRefUpdates::
+ If true, `git-update-ref` will append a line to
+ "$GIT_DIR/logs/<ref>" listing the new SHA1 and the date/time
+ of the update. This information can be used to determine
+ what commit was the tip of a branch "2 days ago". This value
+ is false by default (no logging).
+
core.repositoryFormatVersion::
Internal variable identifying the repository format and layout
version.
diff --git a/Documentation/git-update-ref.txt b/Documentation/git-update-ref.txt
index 475237f..edd39d3 100644
--- a/Documentation/git-update-ref.txt
+++ b/Documentation/git-update-ref.txt
@@ -49,6 +49,25 @@ for reading but not for writing (so we'l
ref symlink to some other tree, if you have copied a whole
archive by creating a symlink tree).
+Logging Updates
+---------------
+If config parameter "core.logRefUpdates" is true then
+`git-update-ref` will append a line to the log file
+"$GIT_DIR/logs/<ref>" (dereferencing all symbolic refs before
+creating the log name) describing the change in ref value. Log lines
+are formatted as:
+
+ . oldsha1 SP newsha1 SP committer LF
++
+Where "oldsha1" is the 40 character hexadecimal value previously
+stored in <ref>, "newsha1" is the 40 character hexadecimal value of
+<newvalue> and "committer" is the committer's name, email address
+and date in the standard GIT committer ident format.
+
+An update will fail (without changing <ref>) if the current user is
+unable to create a new log file, append to the existing log file
+or does not have committer information available.
+
Author
------
Written by Linus Torvalds <torvalds@osdl.org>.
diff --git a/cache.h b/cache.h
index b1300cd..887ce20 100644
--- a/cache.h
+++ b/cache.h
@@ -171,6 +171,7 @@ extern void rollback_index_file(struct c
extern int trust_executable_bit;
extern int assume_unchanged;
extern int prefer_symlink_refs;
+extern int log_ref_updates;
extern int warn_ambiguous_refs;
extern int diff_rename_limit_default;
extern int shared_repository;
diff --git a/config.c b/config.c
index 0f518c9..f8a814e 100644
--- a/config.c
+++ b/config.c
@@ -232,6 +232,11 @@ int git_default_config(const char *var,
return 0;
}
+ if (!strcmp(var, "core.logrefupdates")) {
+ log_ref_updates = git_config_bool(var, value);
+ return 0;
+ }
+
if (!strcmp(var, "core.warnambiguousrefs")) {
warn_ambiguous_refs = git_config_bool(var, value);
return 0;
diff --git a/environment.c b/environment.c
index 444c99e..437266e 100644
--- a/environment.c
+++ b/environment.c
@@ -14,6 +14,7 @@ char git_default_name[MAX_GITNAME];
int trust_executable_bit = 1;
int assume_unchanged = 0;
int prefer_symlink_refs = 0;
+int log_ref_updates = 0;
int warn_ambiguous_refs = 1;
int repository_format_version = 0;
char git_commit_encoding[MAX_ENCODING_LENGTH] = "utf-8";
diff --git a/update-ref.c b/update-ref.c
index fd48742..64fc3db 100644
--- a/update-ref.c
+++ b/update-ref.c
@@ -22,7 +22,7 @@ int main(int argc, char **argv)
const char *refname, *value, *oldval, *path;
char *lockpath;
unsigned char sha1[20], oldsha1[20], currsha1[20];
- int fd, written;
+ int fd, written, pfxlen;
setup_git_directory();
git_config(git_default_config);
@@ -38,7 +38,9 @@ int main(int argc, char **argv)
if (oldval && get_sha1(oldval, oldsha1))
die("%s: not a valid old SHA1", oldval);
- path = resolve_ref(git_path("%s", refname), currsha1, !!oldval);
+ path = git_path("%s", refname);
+ pfxlen = strlen(path) - strlen(refname);
+ path = resolve_ref(path, currsha1, !!oldval);
if (!path)
die("No such ref: %s", refname);
@@ -50,7 +52,7 @@ int main(int argc, char **argv)
exit(0);
}
path = strdup(path);
- lockpath = mkpath("%s.lock", path);
+ lockpath = strdup(mkpath("%s.lock", path));
if (safe_create_leading_directories(lockpath) < 0)
die("Unable to create all of %s", lockpath);
@@ -75,6 +77,46 @@ int main(int argc, char **argv)
}
/*
+ * Write to the log if logging of ref updates is enabled
+ */
+ if (log_ref_updates && memcmp(currsha1, sha1, 20)) {
+ char *logrec, *logpath;
+ const char *comitter;
+ unsigned maxlen, len;
+ int logfd;
+
+ setup_ident();
+ comitter = git_committer_info(1);
+ maxlen = strlen(comitter) + 2*40 + 4;
+ logrec = xmalloc(maxlen);
+ len = snprintf(logrec, maxlen, "%s %s %s\n",
+ sha1_to_hex(currsha1),
+ sha1_to_hex(sha1),
+ comitter);
+ if (len >= maxlen) {
+ unlink(lockpath);
+ die("Internal error formatting log record.");
+ }
+
+ logpath = git_path("logs/%s", path + pfxlen);
+ if (safe_create_leading_directories(logpath) < 0) {
+ unlink(lockpath);
+ die("Unable to create all of %s", logpath);
+ }
+ logfd = open(logpath, O_CREAT | O_APPEND | O_WRONLY, 0666);
+ if (logfd < 0) {
+ unlink(lockpath);
+ die("Unable to append to %s", logpath);
+ }
+ written = write(logfd, logrec, len);
+ if (written != len) {
+ unlink(lockpath);
+ die("Unable to append to %s", logpath);
+ }
+ close(logfd);
+ }
+
+ /*
* Finally, replace the old ref with the new one
*/
if (rename(lockpath, path) < 0) {
--
1.3.2.g7278
^ permalink raw reply related
* Re: [PATCH] Add "--branches" and "--tags" options to git-rev-parse.
From: Junio C Hamano @ 2006-05-13 17:38 UTC (permalink / raw)
To: Sean Estabrooks; +Cc: git
In-Reply-To: <BAYC1-PASMTP0299DC98A51B55188BDF96AEAD0@CEZ.ICE>
Sean Estabrooks <seanlkml@sympatico.ca> writes:
> "git branch" uses rev-parse and can become slow when there are many
> tags. Use the new "--branches" option of rev-parse to speed things up.
Makes sense perhaps.
I understand you added --tags for completeness. Probably it
would make sense to add --remotes if you are shooting for that.
^ permalink raw reply
* Re: daily git packages for debian etch and sarge
From: Junio C Hamano @ 2006-05-13 17:31 UTC (permalink / raw)
To: Jakub Narebski; +Cc: git
In-Reply-To: <e44jji$bmf$1@sea.gmane.org>
Jakub Narebski <jnareb@gmail.com> writes:
> Thomas Glanzmann wrote:
>
>> is there someone who builds and publishes daily automatic git packages
>> of Junios tree for debian sarge / etch (testing)?
>
> http://git.or.cz/download.html
Excuse me, where is the deb package link to daily automatic
build results on that page?
^ permalink raw reply
* Re: Tracking branch history
From: Junio C Hamano @ 2006-05-13 16:43 UTC (permalink / raw)
To: Linus Torvalds; +Cc: Shawn Pearce, git
In-Reply-To: <Pine.LNX.4.64.0605130815550.3866@g5.osdl.org>
Linus Torvalds <torvalds@osdl.org> writes:
> I actually disagree with Junio - I think the logging the name made sense.
> If you have a shared repo with multiple people pushing to the same branch,
> it's interesting to see who does the pushing.
Yes, I agree recording that information is interesting.
My comment was about how it is recorded. In the local case
GIT_COMMITTER_IDENT is what you want as Shawn did in his
original proposal, but remote "pushing into shared repository"
case I do not think it is available in general.
Well, at least that was what I was thinking when I made that
comment. However,
If the pushers arrange to have appropriate environment variables
while receive-pack does its work (.git/config in the target
repository is not an appropriate place to get user.* settings
from in a shared setting), what you say makes perfect sense.
Having the usual enviornment available would be handy to make
the hooks on the receiving end to do useful things anyway, so I
retract that suggestion.
> I also think it might be good to save the oldsha1 value. Yes, it _should_
> always be the previous sha1 logged, but it's interesting to see in case it
> isn't (ie the ref was updated some other way), and it's also interesting
> for the first entry after logging has been enabled.
>
> Linue
Yes, and also what user-level command was used to cause update
the ref; was it a merge from remote, own commit, rewind/rebase?
Junia
;-)
^ permalink raw reply
* Re: Tracking branch history
From: Linus Torvalds @ 2006-05-13 15:20 UTC (permalink / raw)
To: Shawn Pearce; +Cc: Junio C Hamano, git
In-Reply-To: <20060513074328.GB21998@spearce.org>
On Sat, 13 May 2006, Shawn Pearce wrote:
>
> Forget my last patch. This one automatically creates the log file
> by looking for a config value of 'core.logRefUpdates=true'.
Looks better.
I actually disagree with Junio - I think the logging the name made sense.
If you have a shared repo with multiple people pushing to the same branch,
it's interesting to see who does the pushing.
I also think it might be good to save the oldsha1 value. Yes, it _should_
always be the previous sha1 logged, but it's interesting to see in case it
isn't (ie the ref was updated some other way), and it's also interesting
for the first entry after logging has been enabled.
Hmm?
Linue
^ permalink raw reply
* [PATCH] Add "--branches" and "--tags" options to git-rev-parse.
From: Sean Estabrooks @ 2006-05-13 15:13 UTC (permalink / raw)
To: git
"git branch" uses rev-parse and can become slow when there are many
tags. Use the new "--branches" option of rev-parse to speed things up.
Signed-off-by: Sean Estabrooks <seanlkml@sympatico.ca>
---
Documentation/git-rev-parse.txt | 6 ++++++
git-branch.sh | 3 +--
refs.c | 18 ++++++++++++++----
refs.h | 2 ++
rev-parse.c | 8 ++++++++
5 files changed, 31 insertions(+), 6 deletions(-)
7898e1e58b18e992e3d90516fc9e6f3476a385ed
diff --git a/Documentation/git-rev-parse.txt b/Documentation/git-rev-parse.txt
index 8b95df0..c1da2bf 100644
--- a/Documentation/git-rev-parse.txt
+++ b/Documentation/git-rev-parse.txt
@@ -67,6 +67,12 @@ OPTIONS
--all::
Show all refs found in `$GIT_DIR/refs`.
+--branches::
+ Show branch refs found in `$GIT_DIR/refs/heads`.
+
+--tags::
+ Show tag refs found in `$GIT_DIR/refs/tags`.
+
--show-prefix::
When the command is invoked from a subdirectory, show the
path of the current directory relative to the top-level
diff --git a/git-branch.sh b/git-branch.sh
index ebcc898..134e68c 100755
--- a/git-branch.sh
+++ b/git-branch.sh
@@ -82,8 +82,7 @@ done
case "$#" in
0)
- git-rev-parse --symbolic --all |
- sed -ne 's|^refs/heads/||p' |
+ git-rev-parse --symbolic --branches |
sort |
while read ref
do
diff --git a/refs.c b/refs.c
index 275b914..9c29a73 100644
--- a/refs.c
+++ b/refs.c
@@ -114,7 +114,7 @@ int read_ref(const char *filename, unsig
return -1;
}
-static int do_for_each_ref(const char *base, int (*fn)(const char *path, const unsigned char *sha1))
+static int do_for_each_ref(const char *base, int (*fn)(const char *path, const unsigned char *sha1), int trim)
{
int retval = 0;
DIR *dir = opendir(git_path("%s", base));
@@ -146,7 +146,7 @@ static int do_for_each_ref(const char *b
if (stat(git_path("%s", path), &st) < 0)
continue;
if (S_ISDIR(st.st_mode)) {
- retval = do_for_each_ref(path, fn);
+ retval = do_for_each_ref(path, fn, trim);
if (retval)
break;
continue;
@@ -160,7 +160,7 @@ static int do_for_each_ref(const char *b
"commit object!", path);
continue;
}
- retval = fn(path, sha1);
+ retval = fn(path + trim, sha1);
if (retval)
break;
}
@@ -180,7 +180,17 @@ int head_ref(int (*fn)(const char *path,
int for_each_ref(int (*fn)(const char *path, const unsigned char *sha1))
{
- return do_for_each_ref("refs", fn);
+ return do_for_each_ref("refs", fn, 0);
+}
+
+int for_each_tag(int (*fn)(const char *path, const unsigned char *sha1))
+{
+ return do_for_each_ref("refs/tags", fn, 10);
+}
+
+int for_each_branch(int (*fn)(const char *path, const unsigned char *sha1))
+{
+ return do_for_each_ref("refs/heads", fn, 11);
}
static char *ref_file_name(const char *ref)
diff --git a/refs.h b/refs.h
index 2625596..f270b62 100644
--- a/refs.h
+++ b/refs.h
@@ -7,6 +7,8 @@ #define REFS_H
*/
extern int head_ref(int (*fn)(const char *path, const unsigned char *sha1));
extern int for_each_ref(int (*fn)(const char *path, const unsigned char *sha1));
+extern int for_each_tag(int (*fn)(const char *path, const unsigned char *sha1));
+extern int for_each_branch(int (*fn)(const char *path, const unsigned char *sha1));
/** Reads the refs file specified into sha1 **/
extern int get_ref_sha1(const char *ref, unsigned char *sha1);
diff --git a/rev-parse.c b/rev-parse.c
index 62e16af..4eb38de 100644
--- a/rev-parse.c
+++ b/rev-parse.c
@@ -255,6 +255,14 @@ int main(int argc, char **argv)
for_each_ref(show_reference);
continue;
}
+ if (!strcmp(arg, "--branches")) {
+ for_each_branch(show_reference);
+ continue;
+ }
+ if (!strcmp(arg, "--tags")) {
+ for_each_tag(show_reference);
+ continue;
+ }
if (!strcmp(arg, "--show-prefix")) {
if (prefix)
puts(prefix);
--
1.3.2.g419f
^ permalink raw reply related
* Re: Tracking branch history
From: Linus Torvalds @ 2006-05-13 15:11 UTC (permalink / raw)
To: Shawn Pearce; +Cc: Junio C Hamano, git
In-Reply-To: <20060513071753.GA21998@spearce.org>
On Sat, 13 May 2006, Shawn Pearce wrote:
>
> +
> + /*
> + * If logging is required make sure we can append to the log.
> + */
> + logpath = strdup(git_path("logs/%s", path + pfxlen));
I don't think you need the strdup().
I also think you might as well just let the logging silently fail, but
hey, that's up to you.
Linus
^ permalink raw reply
* Re: Tracking branch history
From: Elrond @ 2006-05-13 12:53 UTC (permalink / raw)
To: git
In-Reply-To: <Pine.LNX.4.64.0605121838490.6713@iabervon.org>
Daniel Barkalow <barkalow <at> iabervon.org> writes:
>
> One feature that might make git more intuitive to people is if we were to
> additionally track the history of what commit was the head of each branch
> over time. This is only vaguely related to the history of the content, but
> it's well-defined and sometimes significant.
>
> E.g., if you know that two weeks ago, what you had worked, but it doesn't
> work now, you can use git-bisect to figure out what happened, but first
> you have to figure out what commit it was that you were using two weeks
> ago. Two weeks ago, we had that information, but we didn't keep it.
On a related issue:
Looking at a commit:
commit id-commit
parent id-1
parent id-2
parent id-3
Merge branch 'branch-2', 'branch-3'
One can tell the name of the branches for id-2 and id-3 (branch-2, 3),
but one can't tell the name of id-1.
At the time, those branches were not yet merged, this information was
available easily, even remotely via git-clone.
^ permalink raw reply
* Re: daily git packages for debian etch and sarge
From: Jakub Narebski @ 2006-05-13 12:31 UTC (permalink / raw)
To: git
In-Reply-To: <20060513122401.GC11845@cip.informatik.uni-erlangen.de>
Thomas Glanzmann wrote:
> is there someone who builds and publishes daily automatic git packages
> of Junios tree for debian sarge / etch (testing)?
http://git.or.cz/download.html
--
Jakub Narebski
Warsaw, Poland
^ permalink raw reply
* daily git packages for debian etch and sarge
From: Thomas Glanzmann @ 2006-05-13 12:24 UTC (permalink / raw)
To: GIT
Hello,
is there someone who builds and publishes daily automatic git packages
of Junios tree for debian sarge / etch (testing)?
Thomas
^ permalink raw reply
* Re: [RFC] qgit with tabs
From: Marco Costalba @ 2006-05-13 11:31 UTC (permalink / raw)
To: Pavel Roskin; +Cc: git
In-Reply-To: <20060513070726.qa5ssccws80go044@webmail.spamcop.net>
Hi Pavel,
>
> Just one thing for now. Double click on a file on the "rev list" tab should
> show the patch (what Ctrl-P would do), not the whole file. That would be more
> compatible with gitk, and it's what I normally need if I just browse the latest
> changes in the rev list.
>
Well, double click activates the current top entry in context menu.
This behaviour has not changed from past releases. To show the patch
perhaps you may, as always, double click on the selected revision, in
revisions list.
FWIK gitk does not have a file content viewer.
Thanks
Marco
^ permalink raw reply
* Re: [RFC] qgit with tabs
From: Pavel Roskin @ 2006-05-13 11:07 UTC (permalink / raw)
To: Marco Costalba; +Cc: git
In-Reply-To: <e5bfff550605130344n75e3e55eq533c49fc2a4f5483@mail.gmail.com>
Hello, Marco!
Quoting Marco Costalba <mcostalba@gmail.com>:
> I have pushed some patches that add tabs to qgit UI.
That's _really_ appreciated.
> I don't expect a new release any time soon, but I am interested to
> hear comments, especially on the usability front, so to be able to
> steer new development in advance.
Just one thing for now. Double click on a file on the "rev list" tab should
show the patch (what Ctrl-P would do), not the whole file. That would be more
compatible with gitk, and it's what I normally need if I just browse the latest
changes in the rev list.
> With new UI I found myself more and more using keyboard bindings
> instead of mouse:
>
> - r, p, f to switch to revisions list, patch and file views respectively
>
> - t to toggle tree view
>
> - s to toggle split view (very useful IMHO)
The later is very useful, but a bit hard to discover without checking the menu.
Maybe it should be a button in the toolbar.
> NOTE:
> Due to some repacking on a dumb host probably you need to re-clone:
I don't think re-clone should be needed. I didn't re-clone, yet I could update.
On the other hand, that host sometimes returns something that crashes
git-http-fetch. Sorry, no time to debug it right now. I guess it returns
error messages in HTML without reporting error 404, but git-http-fetch should
be more robust anyway.
--
Regards,
Pavel Roskin
^ permalink raw reply
* [RFC] qgit with tabs
From: Marco Costalba @ 2006-05-13 10:44 UTC (permalink / raw)
To: git
Hi all,
I have pushed some patches that add tabs to qgit UI.
I don't expect a new release any time soon, but I am interested to
hear comments, especially on the usability front, so to be able to
steer new development in advance.
With new UI I found myself more and more using keyboard bindings
instead of mouse:
- r, p, f to switch to revisions list, patch and file views respectively
- t to toggle tree view
- s to toggle split view (very useful IMHO)
NOTE:
Due to some repacking on a dumb host probably you need to re-clone:
git clone http://digilander.libero.it/mcostalba/scm/qgit.git
cd qgit
autoreconf -i
./configure
make
make install-strip
Marco
^ permalink raw reply
* Re: Tracking branch history
From: Shawn Pearce @ 2006-05-13 7:43 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
In-Reply-To: <20060513071753.GA21998@spearce.org>
Shawn Pearce <spearce@spearce.org> wrote:
> Junio C Hamano <junkio@cox.net> wrote:
> > Shawn Pearce <spearce@spearce.org> writes:
> >
> > > git-udpate-ref. So just have it append the ref's history to a file:
> > >
> > > .git/log/refs/heads/$branch
> > >
> > > where the history records are stored as:
> > >
> > > 40 byte commit-ish SHA1
> > > <SP>
> > > <committer>
> > > <LF>
> > >
> > > e.g.:
> > >
> > > cbb6d91d95e523c2b6a6b52577c4be28d18ace83 Shawn O. Pearce <spearce@spearce.org> 1137039378 -0500
> > > ae8c74e96a1e02bbfb7f1a9669b77d6f8ee6c3cf Shawn O. Pearce <spearce@spearce.org> 1136921470 -0500
> > >
> >
> > Because the question we often would want to ask is "two days ago
> > my tip worked but today it does not", recording the timestamp
> > makes sense, but I do not know what the point is for the name
> > and e-mail. If it is in your local repository (i.e. the program
> > that updates the tip ref is not receive-pack which is invoked by
> > your pushing into a remote repo), it will always be you. And in
> > the receive-pack case, the information is not available to begin
> > with (you may have a UNIX UID but that is about it).
Forget my last patch. This one automatically creates the log file
by looking for a config value of 'core.logRefUpdates=true'.
--> -
Log ref updates to logs/refs/<ref>
If config parameter core.logRefUpdates is true then append a line
to .git/logs/refs/<ref> whenever git-update-ref <ref> is executed.
Each log line contains the following information:
40 byte tree-ish SHA1
<SP>
date/time
<LF>
where date/time is the current date, time and timezone in the
standard GIT date format. If the caller is unable to append to
the log file then git-update-ref will fail without updating <ref>.
---
Documentation/config.txt | 7 ++++++
Documentation/git-update-ref.txt | 17 +++++++++++++++
cache.h | 1 +
config.c | 5 ++++
environment.c | 1 +
update-ref.c | 43 +++++++++++++++++++++++++++++++++++---
6 files changed, 71 insertions(+), 3 deletions(-)
cac86f2df9a52d94cb03038e267934c67f04122b
diff --git a/Documentation/config.txt b/Documentation/config.txt
index d1a4bec..f06695c 100644
--- a/Documentation/config.txt
+++ b/Documentation/config.txt
@@ -70,6 +70,13 @@ core.preferSymlinkRefs::
This is sometimes needed to work with old scripts that
expect HEAD to be a symbolic link.
+core.logRefUpdates::
+ If true, `git-update-ref` will append a line to
+ "$GIT_DIR/logs/<ref>" listing the new SHA1 and the date/time
+ of the update. This information can be used to determine
+ what commit was the tip of a branch "2 days ago". This value
+ is false by default (no logging).
+
core.repositoryFormatVersion::
Internal variable identifying the repository format and layout
version.
diff --git a/Documentation/git-update-ref.txt b/Documentation/git-update-ref.txt
index 475237f..8c46263 100644
--- a/Documentation/git-update-ref.txt
+++ b/Documentation/git-update-ref.txt
@@ -49,6 +49,23 @@ for reading but not for writing (so we'l
ref symlink to some other tree, if you have copied a whole
archive by creating a symlink tree).
+Logging Updates
+---------------
+If config parameter "core.logRefUpdates" is true then
+`git-update-ref` will append a line to the log file
+"$GIT_DIR/logs/<ref>" (dereferencing all symbolic refs before
+creating the log name) describing the change in ref value. Log lines
+are formatted as:
+
+ . sha1 SP date LF
++
+Where "sha1" is the 40 character hexadecimal value of <newvalue>
+and "date" is the current date/time and timezone in the standard
+GIT date format.
+
+An update will fail (without changing <ref>) if the current user is
+unable to create a new log file or append to the existing log file.
+
Author
------
Written by Linus Torvalds <torvalds@osdl.org>.
diff --git a/cache.h b/cache.h
index b1300cd..887ce20 100644
--- a/cache.h
+++ b/cache.h
@@ -171,6 +171,7 @@ extern void rollback_index_file(struct c
extern int trust_executable_bit;
extern int assume_unchanged;
extern int prefer_symlink_refs;
+extern int log_ref_updates;
extern int warn_ambiguous_refs;
extern int diff_rename_limit_default;
extern int shared_repository;
diff --git a/config.c b/config.c
index 0f518c9..f8a814e 100644
--- a/config.c
+++ b/config.c
@@ -232,6 +232,11 @@ int git_default_config(const char *var,
return 0;
}
+ if (!strcmp(var, "core.logrefupdates")) {
+ log_ref_updates = git_config_bool(var, value);
+ return 0;
+ }
+
if (!strcmp(var, "core.warnambiguousrefs")) {
warn_ambiguous_refs = git_config_bool(var, value);
return 0;
diff --git a/environment.c b/environment.c
index 444c99e..437266e 100644
--- a/environment.c
+++ b/environment.c
@@ -14,6 +14,7 @@ char git_default_name[MAX_GITNAME];
int trust_executable_bit = 1;
int assume_unchanged = 0;
int prefer_symlink_refs = 0;
+int log_ref_updates = 0;
int warn_ambiguous_refs = 1;
int repository_format_version = 0;
char git_commit_encoding[MAX_ENCODING_LENGTH] = "utf-8";
diff --git a/update-ref.c b/update-ref.c
index fd48742..c231760 100644
--- a/update-ref.c
+++ b/update-ref.c
@@ -22,7 +22,7 @@ int main(int argc, char **argv)
const char *refname, *value, *oldval, *path;
char *lockpath;
unsigned char sha1[20], oldsha1[20], currsha1[20];
- int fd, written;
+ int fd, written, pfxlen;
setup_git_directory();
git_config(git_default_config);
@@ -38,7 +38,9 @@ int main(int argc, char **argv)
if (oldval && get_sha1(oldval, oldsha1))
die("%s: not a valid old SHA1", oldval);
- path = resolve_ref(git_path("%s", refname), currsha1, !!oldval);
+ path = git_path("%s", refname);
+ pfxlen = strlen(path) - strlen(refname);
+ path = resolve_ref(path, currsha1, !!oldval);
if (!path)
die("No such ref: %s", refname);
@@ -50,7 +52,7 @@ int main(int argc, char **argv)
exit(0);
}
path = strdup(path);
- lockpath = mkpath("%s.lock", path);
+ lockpath = strdup(mkpath("%s.lock", path));
if (safe_create_leading_directories(lockpath) < 0)
die("Unable to create all of %s", lockpath);
@@ -75,6 +77,41 @@ int main(int argc, char **argv)
}
/*
+ * Write to the log if logging of ref updates is enabled
+ */
+ if (log_ref_updates) {
+ char *logpath;
+ char now[50];
+ char logrec[100];
+ unsigned len;
+ int logfd;
+
+ datestamp(now, sizeof(now));
+ len = snprintf(logrec, sizeof(logrec), "%s %s\n", sha1_to_hex(sha1), now);
+ if (len >= sizeof(logrec)) {
+ unlink(lockpath);
+ die("Internal error formatting log record.");
+ }
+
+ logpath = git_path("logs/%s", path + pfxlen);
+ if (safe_create_leading_directories(logpath) < 0) {
+ unlink(lockpath);
+ die("Unable to create all of %s", logpath);
+ }
+ logfd = open(logpath, O_CREAT | O_APPEND | O_WRONLY, 0666);
+ if (logfd < 0) {
+ unlink(lockpath);
+ die("Unable to append to log %s", logpath);
+ }
+ written = write(logfd, logrec, len);
+ if (written != len) {
+ unlink(lockpath);
+ die("Unable to append to %s", logpath);
+ }
+ close(logfd);
+ }
+
+ /*
* Finally, replace the old ref with the new one
*/
if (rename(lockpath, path) < 0) {
--
1.3.2.g7278
^ permalink raw reply related
* Re: Tracking branch history
From: Shawn Pearce @ 2006-05-13 7:17 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
In-Reply-To: <7vody2v7yr.fsf@assigned-by-dhcp.cox.net>
Junio C Hamano <junkio@cox.net> wrote:
> Shawn Pearce <spearce@spearce.org> writes:
>
> > git-udpate-ref. So just have it append the ref's history to a file:
> >
> > .git/log/refs/heads/$branch
> >
> > where the history records are stored as:
> >
> > 40 byte commit-ish SHA1
> > <SP>
> > <committer>
> > <LF>
> >
> > e.g.:
> >
> > cbb6d91d95e523c2b6a6b52577c4be28d18ace83 Shawn O. Pearce <spearce@spearce.org> 1137039378 -0500
> > ae8c74e96a1e02bbfb7f1a9669b77d6f8ee6c3cf Shawn O. Pearce <spearce@spearce.org> 1136921470 -0500
> >
>
> Because the question we often would want to ask is "two days ago
> my tip worked but today it does not", recording the timestamp
> makes sense, but I do not know what the point is for the name
> and e-mail. If it is in your local repository (i.e. the program
> that updates the tip ref is not receive-pack which is invoked by
> your pushing into a remote repo), it will always be you. And in
> the receive-pack case, the information is not available to begin
> with (you may have a UNIX UID but that is about it).
Agreed. Prototype patch below.
While writing this I discovered at least two chunks of GIT which
don't use git-update-ref: fetch.c and upload-pack.c. fetch.c uses
the APIs in refs.c but upload-pack.c doesn't. I spent a couple of
hours trying to convert update-ref.c to use the APIs in refs.c so
I could just put the logging change there, but that turned out to
be more difficult than expected for a simple prototype so it all
went out the window.
-- >-
Log ref updates to logs/refs/<refname>
If .git/logs/refs/<refname> exists then append a line to it whenever
git-update-ref <refname> is executed. Each log line contains the
following information:
40 byte tree-ish SHA1
<SP>
date/time
<LF>
where date/time is the current date, time and timezone in the
standard GIT date format. If the caller is unable to append to
the log file and the log file exists then git-update-ref will fail
without updating <refname>.
---
Documentation/git-update-ref.txt | 15 ++++++++++++++
update-ref.c | 41 +++++++++++++++++++++++++++++++++++---
2 files changed, 53 insertions(+), 3 deletions(-)
8f1ccd3b0eda9d54eca37af178113c91174e81ca
diff --git a/Documentation/git-update-ref.txt b/Documentation/git-update-ref.txt
index 475237f..d314786 100644
--- a/Documentation/git-update-ref.txt
+++ b/Documentation/git-update-ref.txt
@@ -49,6 +49,21 @@ for reading but not for writing (so we'l
ref symlink to some other tree, if you have copied a whole
archive by creating a symlink tree).
+Logging Updates
+---------------
+If "$GIT_DIR/logs/<ref>" (possibly dereferencing symbolic refs)
+exists then `git-update-ref` will append a line to the log file
+describing the change in ref value. Log lines are formatted as:
+
+ . sha1 SP date LF
++
+Where "sha1" is the 40 character hexadecimal value of <newvalue>
+and "date" is the current date/time and timezone in the standard
+GIT date format.
+
+An update will fail (without changing <ref>) if the log file
+exists but the current user is unable to append to the file.
+
Author
------
Written by Linus Torvalds <torvalds@osdl.org>.
diff --git a/update-ref.c b/update-ref.c
index fd48742..bffe5f9 100644
--- a/update-ref.c
+++ b/update-ref.c
@@ -20,9 +20,9 @@ int main(int argc, char **argv)
{
char *hex;
const char *refname, *value, *oldval, *path;
- char *lockpath;
+ char *lockpath, *logpath;
unsigned char sha1[20], oldsha1[20], currsha1[20];
- int fd, written;
+ int fd, logfd, written, pfxlen;
setup_git_directory();
git_config(git_default_config);
@@ -38,7 +38,9 @@ int main(int argc, char **argv)
if (oldval && get_sha1(oldval, oldsha1))
die("%s: not a valid old SHA1", oldval);
- path = resolve_ref(git_path("%s", refname), currsha1, !!oldval);
+ path = git_path("%s", refname);
+ pfxlen = strlen(path) - strlen(refname);
+ path = resolve_ref(path, currsha1, !!oldval);
if (!path)
die("No such ref: %s", refname);
@@ -50,6 +52,17 @@ int main(int argc, char **argv)
exit(0);
}
path = strdup(path);
+
+ /*
+ * If logging is required make sure we can append to the log.
+ */
+ logpath = strdup(git_path("logs/%s", path + pfxlen));
+ logfd = open(logpath, O_APPEND | O_WRONLY, 0);
+ if (logfd < 0 && errno != ENOENT)
+ die("Unable to append to log %s", logpath);
+ if (logfd >= 0)
+ setup_ident();
+
lockpath = mkpath("%s.lock", path);
if (safe_create_leading_directories(lockpath) < 0)
die("Unable to create all of %s", lockpath);
@@ -75,6 +88,28 @@ int main(int argc, char **argv)
}
/*
+ * Write to the log, if it was opened.
+ */
+ if (logfd >= 0) {
+ char now[50];
+ char logrec[100];
+ unsigned len;
+
+ datestamp(now, sizeof(now));
+ len = snprintf(logrec, sizeof(logrec), "%s %s\n", sha1_to_hex(sha1), now);
+ if (len >= sizeof(logrec)) {
+ unlink(lockpath);
+ die("Internal error formatting log record.");
+ }
+ written = write(logfd, logrec, len);
+ if (written != len) {
+ unlink(lockpath);
+ die("Unable to append to %s", logpath);
+ }
+ close(logfd);
+ }
+
+ /*
* Finally, replace the old ref with the new one
*/
if (rename(lockpath, path) < 0) {
--
1.3.2.g7278
^ permalink raw reply related
* Re: [PATCH] Fix git-pack-objects for 64-bit platforms
From: Junio C Hamano @ 2006-05-13 5:58 UTC (permalink / raw)
To: Linus Torvalds; +Cc: Dennis Stosberg, git
In-Reply-To: <Pine.LNX.4.64.0605111218380.3866@g5.osdl.org>
Linus Torvalds <torvalds@osdl.org> writes:
> Since I _do_ have a 64-bit big-endian architecture, I decided to install
> some of the 64-bit development libraries that I didn't already have, and I
> added "-m64" to the compiler flags.
>
> All the tests seem to pass with the simple fix (and without it, we do
> indeed fail at least t5700-clone-reference.sh).
>
> Of course, there might well be something else that doesn't get coverage,
> but passing all tests is at least a good sign. And since x86-64 has been
> getting pretty extensive coverage, I don't think we have a lot of 64-bit
> bugs per se, this one just happened to hide.
>
> Linus
Thanks, both. This is what I am thinking of applying (but I am
sort of burned-out right now after a two-day meeting with my
sponsors, so the real work will be tomorrow).
It takes the uint32_t version but matches another place to use
that type instead of "int" (which would not matter in next 10
years perhaps).
-- >8 --
diff --git a/pack-objects.c b/pack-objects.c
index c0acc46..a81d609 100644
--- a/pack-objects.c
+++ b/pack-objects.c
@@ -156,7 +156,7 @@ static void prepare_pack_revindex(struct
rix->revindex = xmalloc(sizeof(unsigned long) * (num_ent + 1));
for (i = 0; i < num_ent; i++) {
- long hl = *((long *)(index + 24 * i));
+ uint32_t hl = *((uint32_t *)(index + 24 * i));
rix->revindex[i] = ntohl(hl);
}
/* This knows the pack format -- the 20-byte trailer
diff --git a/sha1_file.c b/sha1_file.c
index f2d33af..642c45a 100644
--- a/sha1_file.c
+++ b/sha1_file.c
@@ -1126,7 +1126,7 @@ int find_pack_entry_one(const unsigned c
int mi = (lo + hi) / 2;
int cmp = memcmp(index + 24 * mi + 4, sha1, 20);
if (!cmp) {
- e->offset = ntohl(*((int*)(index + 24 * mi)));
+ e->offset = ntohl(*((uint32_t *)(index + 24 * mi)));
memcpy(e->sha1, sha1, 20);
e->p = p;
return 1;
^ permalink raw reply related
* Re: Tracking branch history
From: Junio C Hamano @ 2006-05-13 4:56 UTC (permalink / raw)
To: Shawn Pearce; +Cc: git
In-Reply-To: <20060513034051.GA21586@spearce.org>
Shawn Pearce <spearce@spearce.org> writes:
> git-udpate-ref. So just have it append the ref's history to a file:
>
> .git/log/refs/heads/$branch
>
> where the history records are stored as:
>
> 40 byte commit-ish SHA1
> <SP>
> <committer>
> <LF>
>
> e.g.:
>
> cbb6d91d95e523c2b6a6b52577c4be28d18ace83 Shawn O. Pearce <spearce@spearce.org> 1137039378 -0500
> ae8c74e96a1e02bbfb7f1a9669b77d6f8ee6c3cf Shawn O. Pearce <spearce@spearce.org> 1136921470 -0500
>
Because the question we often would want to ask is "two days ago
my tip worked but today it does not", recording the timestamp
makes sense, but I do not know what the point is for the name
and e-mail. If it is in your local repository (i.e. the program
that updates the tip ref is not receive-pack which is invoked by
your pushing into a remote repo), it will always be you. And in
the receive-pack case, the information is not available to begin
with (you may have a UNIX UID but that is about it).
^ permalink raw reply
* Re: Tracking branch history
From: Linus Torvalds @ 2006-05-13 4:38 UTC (permalink / raw)
To: Shawn Pearce; +Cc: Daniel Barkalow, git
In-Reply-To: <20060513034051.GA21586@spearce.org>
On Fri, 12 May 2006, Shawn Pearce wrote:
>
> Why not intergrate this into git-update-ref. Almost every tool which
> deals with a GIT repository (aside from my pure-Java Eclipse plugin
> which is still a major work-in-process) performs ref changes through
> git-udpate-ref. So just have it append the ref's history to a file:
>
> .git/log/refs/heads/$branch
>
> where the history records are stored as:
>
> 40 byte commit-ish SHA1
> <SP>
> <committer>
> <LF>
Sure. Except it's not really "committer", in the ordinary sense (there's
no "commit" for a fast-forward). But yes, re-using that format (with date
and all) makes sense.
> Of course a major issue here is locking the log file during the ref
> update, but it looks like it might just be safe to append the entry
> to the log file right after the re_verify and before the rename.
I'd suggest just opening it with O_APPEND, and doing the update with a
single write() system call. Let the OS do the locking for you.
Linus
^ permalink raw reply
* Re: Tracking branch history
From: Daniel Barkalow @ 2006-05-13 4:27 UTC (permalink / raw)
To: Linus Torvalds; +Cc: git
In-Reply-To: <Pine.LNX.4.64.0605121656350.3866@g5.osdl.org>
On Fri, 12 May 2006, Linus Torvalds wrote:
> Btw, the real problem with this is how to use it.
>
> The only really valid use I see is to use it for date-based things, ie if
> given a date, look up the most recent commit ID that is older than the
> date in question. No other op seems to really make sense, but that one
> does.
>
> Now, the one other operation that is semantically sensible is to use the
> list of commits to figure out a "path" through the commit space. However,
> that path won't actually even be well-defined (a fast-forward pull/merge
> can and often /will/ update the history in a way where it's impossible to
> select one particular path to the previous commit listed in the commit
> log).
I think that jumping around with reset is necessary to make this actually
complicated; a fast-forward only happens if the new value descends from
the old value, and a merge obviously descends from the old value. Sure,
the non-linear history added by a merge will still be non-linear, but
from the local user's point of view, it was all added in bulk by the
merge.
I think the program creating the history should note the tricky cases,
where the new value doesn't descend from the old value, which should be
easy to identify. I'm not sure what should actually be done to report a
reset in a changelog, either. The section of the log just before the reset
is clearly a false start of some sort, and you probably want to do
something special to list the commits which don't actually lead to the
current state, but you probably want to report them, in case the reason
you'd looking through this is that there was some benefit to a version
that you ended up discarding, and you want to revisit that attempt.
I think in the always-forward case, there's a useful optimization to be
had by having the rev-list-equivalent actually binning commits by the
earliest points that descend from them, so you don't trace the local
branch back to where other branches forked off over and over. But it seems
to me otherwise pretty simple.
-Daniel
*This .sig left intentionally blank*
^ permalink raw reply
* Re: Tracking branch history
From: Shawn Pearce @ 2006-05-13 3:40 UTC (permalink / raw)
To: Linus Torvalds; +Cc: Daniel Barkalow, git
In-Reply-To: <Pine.LNX.4.64.0605121640210.3866@g5.osdl.org>
Linus Torvalds <torvalds@osdl.org> wrote:
>
> On Fri, 12 May 2006, Daniel Barkalow wrote:
> >
> > One feature that might make git more intuitive to people is if we were to
> > additionally track the history of what commit was the head of each branch
> > over time. This is only vaguely related to the history of the content, but
> > it's well-defined and sometimes significant.
> >
> > E.g., if you know that two weeks ago, what you had worked, but it doesn't
> > work now, you can use git-bisect to figure out what happened, but first
> > you have to figure out what commit it was that you were using two weeks
> > ago. Two weeks ago, we had that information, but we didn't keep it.
>
> Note that this is possible, but it must be done literally as a separate
> history from the commit history.
>
> IOW, a good (?) way to do it is to literally have a commit hook that
> basically just does
>
> echo $new >> .git/$branch-commit-history
>
> possibly together with a datestamp thing (ie it could be something like
> "echo $new "$USER" $(date)" rather than just the commit SHA1).
Why not intergrate this into git-update-ref. Almost every tool which
deals with a GIT repository (aside from my pure-Java Eclipse plugin
which is still a major work-in-process) performs ref changes through
git-udpate-ref. So just have it append the ref's history to a file:
.git/log/refs/heads/$branch
where the history records are stored as:
40 byte commit-ish SHA1
<SP>
<committer>
<LF>
e.g.:
cbb6d91d95e523c2b6a6b52577c4be28d18ace83 Shawn O. Pearce <spearce@spearce.org> 1137039378 -0500
ae8c74e96a1e02bbfb7f1a9669b77d6f8ee6c3cf Shawn O. Pearce <spearce@spearce.org> 1136921470 -0500
Of course a major issue here is locking the log file during the ref
update, but it looks like it might just be safe to append the entry
to the log file right after the re_verify and before the rename.
I wouldn't have git-update-ref create the log file. I'd would only
have it append if the log already exists.
Hmm, this actually looks like it would be really easy. Maybe I'll
hack up an RFC patch this evening after dinner.
--
Shawn.
^ permalink raw reply
* Re: Tracking branch history
From: Linus Torvalds @ 2006-05-13 0:03 UTC (permalink / raw)
To: Daniel Barkalow; +Cc: git
In-Reply-To: <Pine.LNX.4.64.0605121640210.3866@g5.osdl.org>
On Fri, 12 May 2006, Linus Torvalds wrote:
>
> IOW, a good (?) way to do it is to literally have a commit hook that
> basically just does
>
> echo $new >> .git/$branch-commit-history
>
> possibly together with a datestamp thing (ie it could be something like
> "echo $new "$USER" $(date)" rather than just the commit SHA1).
Btw, the real problem with this is how to use it.
The only really valid use I see is to use it for date-based things, ie if
given a date, look up the most recent commit ID that is older than the
date in question. No other op seems to really make sense, but that one
does.
Now, the one other operation that is semantically sensible is to use the
list of commits to figure out a "path" through the commit space. However,
that path won't actually even be well-defined (a fast-forward pull/merge
can and often /will/ update the history in a way where it's impossible to
select one particular path to the previous commit listed in the commit
log).
The other thing that makes the "path" thing hard is that it's just
fundamentally a pretty hard thing to calculate, even when it would result
in one unambiguous path. I _believe_ that it comes close to what "git
bisect" does, and that the bisect algorithm could probably be used to
always create _a_ path between each commit (is just pick successive
half-way-points - the commit list _should_ always have a direct dominance
relationship, but the bisection algorithm should do something half-way
sane even if you "jump about" by "git reset" or something).
It might be interesting to see if it's somethign that can be done
reasonably efficiently.
Linus
^ permalink raw reply
* Re: Tracking branch history
From: Linus Torvalds @ 2006-05-12 23:45 UTC (permalink / raw)
To: Daniel Barkalow; +Cc: git
In-Reply-To: <Pine.LNX.4.64.0605121838490.6713@iabervon.org>
On Fri, 12 May 2006, Daniel Barkalow wrote:
>
> One feature that might make git more intuitive to people is if we were to
> additionally track the history of what commit was the head of each branch
> over time. This is only vaguely related to the history of the content, but
> it's well-defined and sometimes significant.
>
> E.g., if you know that two weeks ago, what you had worked, but it doesn't
> work now, you can use git-bisect to figure out what happened, but first
> you have to figure out what commit it was that you were using two weeks
> ago. Two weeks ago, we had that information, but we didn't keep it.
Note that this is possible, but it must be done literally as a separate
history from the commit history.
IOW, a good (?) way to do it is to literally have a commit hook that
basically just does
echo $new >> .git/$branch-commit-history
possibly together with a datestamp thing (ie it could be something like
"echo $new "$USER" $(date)" rather than just the commit SHA1).
Make sure that not just "git commit", but anything else that changes the
branch (notably, "git fetch" and a fast-forward merge as a result of an
explicit merge or a "git pull") would also do this same thing.
But realize that this is really purely a per-repository logging thing, and
not really bound to the actual git history any way.
Linus
^ permalink raw reply
* Tracking branch history
From: Daniel Barkalow @ 2006-05-12 23:18 UTC (permalink / raw)
To: git
One feature that might make git more intuitive to people is if we were to
additionally track the history of what commit was the head of each branch
over time. This is only vaguely related to the history of the content, but
it's well-defined and sometimes significant.
E.g., if you know that two weeks ago, what you had worked, but it doesn't
work now, you can use git-bisect to figure out what happened, but first
you have to figure out what commit it was that you were using two weeks
ago. Two weeks ago, we had that information, but we didn't keep it.
It would probably also be useful for showing changelogs in a
locally-useful order. If you merge in a tree that's been in separate
development for a long time, the commits in that tree will be interleaved
in commit date with the commits you did locally. You tend to want to
attribute all of the changes that happened in the merge to the time of the
merge, but that commit object isn't going to tell you anything useful,
because it may have been done by the other tree (and you fast-forwarded to
the merge). In fact, you may want to attribute the changes to the
fast-forward, which can't recorded in the content history, because nothing
happened to the content. On the other hand, if we were to also record the
branch history, we could give output which shows changes in the order they
reached the local tree (then ordered by the commit tree), just by having
it do:
<time now>
git log <head-as-of-before>..<head-of-of-now>
<time before>
git log <head-as-of-before-that>..<head-as-of-before>
<time before-that>
and so forth.
-Daniel
*This .sig left intentionally blank*
^ permalink raw reply
* git-mailinfo '-u' argument should be default.
From: David Woodhouse @ 2006-05-12 16:46 UTC (permalink / raw)
To: git
If you apply a patch with 'git-am', it takes the raw content of the
From: header, in whatever character set that happens to be, and puts
that content, untagged, into the commit object.
That is almost _never_ the right thing to do, surely? Raw data in
untagged character sets is marginally better than line noise.
We should default to the '-u' behaviour, which converts to the character
set which the git repo is stored in. It's not just for converting to
UTF-8, although it looks like it was in the past. Now, however, it
converts to the character set defined in the configuration. So even if
it's a Luddite who for some reason is sticking with an obsolete
character set, it gets that right.
The only option which makes sense _other_ than that would be to just
stick the RFC2047-encoded original From: header into the commit, surely?
--
dwmw2
^ permalink raw reply
* Re: git-bisect failed me again
From: Linus Torvalds @ 2006-05-12 16:11 UTC (permalink / raw)
To: Andrew Morton; +Cc: junkio, git
In-Reply-To: <Pine.LNX.4.64.0605120823170.3866@g5.osdl.org>
On Fri, 12 May 2006, Linus Torvalds wrote:
>
> But git isn't linear. Never has been. The fact that commits get (roughtly)
> sorted by date (modified by their ancestry relationships either subtly or
> grossly depending on whether --topo-sort is off or on) does not make
> anything linear.
Note that totally independently of sort order (whether "topo-order" or the
normal cheaper "order by date, but at least one chain of parenthood always
first"), you _will_ get the situation that a commit that was shown "last"
in a linear list is actually merged long before.
The simplest case is this:
merge
| \
A \
| \
B \
| X
C |
| Y
D |
| Z
.. ..
where the "main branch" is the A-B-C-D.. line of history, and the merge
brings in another "X-Y-Z" line of history.
Now, the A-B-C branch may have gotten a lot more recent love and
attention, and when you linearize it, since the normal ordering tends to
show it in a date-like order, you may get a list of commits like
merge
A
B
C
D
..
X
Y
Z
..
which makes you think that "A" is much more recent than "X". That may be
actually be _true_, but:
- 'X' actually _showed_up_ in the mainline much later than A. So, if you
track another persons tree like this, X as a commit may be 2 weeks old,
but it might not have been in the tree you tracked yesterday, because
it hadn't been _merged_ until today.
So in a very real sense, from your standpoint, 'X' may be the 'recent'
one, because you hadn't seen it before, but you _had_ seen 'A'
yesterday.
- Equally importantly, 'A' very much is _not_ a descendant of 'X' (ie,
'X' is _not_ reachable from 'A'). So even though 'A' is in a time-sense
much more recent than 'X', you can't say "it's the most recent commit,
so if there's a bug in any of the series, the bug must have been
visible at point 'A'".
This is why it's wrong to look at _any_ linearized list of commits and
imply any ordering what-so-ever. There simply is no list ordering that
guarantees anything at all, because even with "topo-sort", the only thing
we guarantee is that commits that are directly related to each other will
always sort the child before its parents. So even there, you can't
actually say that one commit "dominates" another commit unless you end up
looking at the parenthood chain (and merges are really important).
[ Strictly speaking, there is exactly _one_ thing you can say from just
seeing a list of commits: _if_ that list includes all types of commits
(ie notably merges and empty changes) _and_ if that list was generated
with just one "top" commit, then the first commit on the list will
dominate all other commits. But that's literally the only real ordering
you can ever know from just a list.
So looking at the first commit in a list is actually valid, but only if
you included all the merges and only if the list was generated by a git
command, and not sorted by any other criteria ]
Linus
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox