* Re: Fix git-rev-parse breakage
From: Junio C Hamano @ 2005-08-24 18:52 UTC (permalink / raw)
To: Linus Torvalds; +Cc: git
In-Reply-To: <Pine.LNX.4.58.0508231908170.3317@g5.osdl.org>
Linus Torvalds <torvalds@osdl.org> writes:
> The --flags cleanup caused problems: we used to depend on the fact that
> "revs_only" magically suppressed flags, adn that assumption was broken by
> the recent fixes.
>
> It wasn't a good assumption in the first place, so instead of
> re-introducing it, let's just get rid of it.
>
> This makes "--revs-only" imply "--no-flags".
I was taking a look at this once again after noticing that I
haven't taking any action on it. But now I am a bit confused
reading the above. The first two paragraphs tells me
"--revs-only implied --no-flags and we used to depend on it, but
that is not a right thing so get rid of that assumption" (which
I agree is a good change", and the last sentense says
opposite...
And the code makes --revs-only imply --no-flags.
Here is my thinking, requesting for a sanity check.
* git-whatchanged wants to use it to tell rev-list arguments
from rev-tree arguments. You _do_ want to pick --max-count=10
or --merge-order in this case, and --revs-only implying
--no-flags would make this impossible.
* git-log-script uses it once to make sure it has one commit to
start at, and lacks --no-flags by mistake.
* git-bisect uses it to validate the parameter is a valid ref,
but does not use --verify.
This trivial patch fixes the latter two.
---
diff --git a/git-log-script b/git-log-script
--- a/git-log-script
+++ b/git-log-script
@@ -1,4 +1,4 @@
#!/bin/sh
-revs=$(git-rev-parse --revs-only --default HEAD "$@") || exit
+revs=$(git-rev-parse --revs-only --no-flags --default HEAD "$@") || exit
[ "$revs" ] || die "No HEAD ref"
git-rev-list --pretty $(git-rev-parse --default HEAD "$@") | LESS=-S ${PAGER:-less}
diff --git a/git-bisect-script b/git-bisect-script
--- a/git-bisect-script
+++ b/git-bisect-script
@@ -67,7 +67,7 @@ bisect_good() {
bisect_autostart
case "$#" in
0) revs=$(git-rev-parse --verify HEAD) || exit ;;
- *) revs=$(git-rev-parse --revs-only "$@") || exit ;;
+ *) revs=$(git-rev-parse --revs-only --verify "$@") || exit ;;
esac
for rev in $revs
do
^ permalink raw reply
* Re: baffled again
From: Linus Torvalds @ 2005-08-24 18:57 UTC (permalink / raw)
To: Junio C Hamano; +Cc: tony.luck, git
In-Reply-To: <Pine.LNX.4.58.0508241140290.3317@g5.osdl.org>
On Wed, 24 Aug 2005, Linus Torvalds wrote:
>
> Basically, he had two branches, A and B, and both contained the same patch
> (but _not_ the same commit). One undid it, the other did not. There's no
> real way to say which one is "correct", and both cases clearly merge
> perfectly, so both outcomes "patch applied" and "patch reverted" are
> really equally valid.
In fact, the case that git selected ("patch applied"), is not only the one
that is very fundamentally the one git will always select in this kind of
situation - in some respects is actually the nicer choice of the two.
While it may cause problems (ie the revert was the right thing to do),
it's at least the state that is less likely to be "lost". Having a revert
disappear is likely better than having a real change disappear. The
reaction to the reverted code showing up again is likely "damn, won't that
bug ever go away, I fixed it once already" - but at least people will see
that it's fair: "it was applied twice, so let's revert it twice".
In contrast, the reaction to a patch going away is likely just very
confusing: you have two people applying it, but only one reverting it will
revert both, while the first person who applied it may never have realized
it got reverted.
Linus
^ permalink raw reply
* Re: [RFC] undo and redo
From: Linus Torvalds @ 2005-08-24 18:51 UTC (permalink / raw)
To: Carl Baldwin; +Cc: git
In-Reply-To: <20050824181004.GA18790@hpsvcnb.fc.hp.com>
On Wed, 24 Aug 2005, Carl Baldwin wrote:
>
> Oops. I forgot to actually exit from the script if git-diff-files is
> non-empty.
>
> Also, looking at it now, I don't think keeping undo information in a
> stack is the right thing. But keeping more than just one would be good.
> Oh well, my first shot is never perfect. ;-)
I would actually argue that
git checkout -b newbranch <undo-point>
is the perfect undo.
It leaves the old state in the old branch, and creates a new branch (and
checks it out) with the state you want to revert to. The advantage is
exactly that there is no "stack" of undo's: you can have multiple
independent undo's pending, and you can continue development at any of
them. And merge the results together.
Of course, right now we don't have a "delete branch" command, but it's
really as simple as
rm .git/refs/heads/branchname
(and eventually you may want to do a "git prune" to get rid of stale
objects, but that's a separate issue).
Linus
^ permalink raw reply
* Re: Fix git-rev-parse breakage
From: Linus Torvalds @ 2005-08-24 19:03 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
In-Reply-To: <7v4q9fdv5w.fsf@assigned-by-dhcp.cox.net>
On Wed, 24 Aug 2005, Junio C Hamano wrote:
> that is not a right thing so get rid of that assumption" (which
> I agree is a good change", and the last sentense says
> opposite...
Well, the patch makes it an _explicit_ assumption, instead of a very
subtly hidden one from the code-flow. It was the non-obvious hidden
assumption that caused the bug.
> Here is my thinking, requesting for a sanity check.
>
> * git-whatchanged wants to use it to tell rev-list arguments
> from rev-tree arguments. You _do_ want to pick --max-count=10
> or --merge-order in this case, and --revs-only implying
> --no-flags would make this impossible.
Fair enough. However, there are two kinds of flags: the "revision flags",
and the "-p" kind of flags.
And the problem was that "git-whatchanged -p" didn't work any more,
because we passed "-p" along to "git-rev-list". Gaah.
Linus
^ permalink raw reply
* Re: baffled again
From: Daniel Barkalow @ 2005-08-24 19:33 UTC (permalink / raw)
To: Linus Torvalds; +Cc: Junio C Hamano, tony.luck, git
In-Reply-To: <Pine.LNX.4.58.0508241140290.3317@g5.osdl.org>
On Wed, 24 Aug 2005, Linus Torvalds wrote:
> Now, if the shared patch hadn't been a patch, but a shared _commit_, then
> the thing would have been unambiguous - the shared commit would have been
> the merge point, and the revert would have clearly undone that shared
> commit.
Actually, it was a shared commit
(4aec0fb12267718c750475f3404337ad13caa8f5), which was (an ancestor of) a
candidate merge point, but wasn't the one selected. Since a different one
was chosen, it looked to the 3-way merge like a shared patch (since it
ignores the untaken parent in the merges in the history).
This should be fixable, but it'll require more cleverness in read-tree.
-Daniel
*This .sig left intentionally blank*
^ permalink raw reply
* Re: [RFC] undo and redo
From: Carl Baldwin @ 2005-08-24 19:56 UTC (permalink / raw)
To: Linus Torvalds; +Cc: Carl Baldwin, git
In-Reply-To: <Pine.LNX.4.58.0508241148480.3317@g5.osdl.org>
On Wed, Aug 24, 2005 at 11:51:32AM -0700, Linus Torvalds wrote:
>
>
> On Wed, 24 Aug 2005, Carl Baldwin wrote:
> >
> > Oops. I forgot to actually exit from the script if git-diff-files is
> > non-empty.
> >
> > Also, looking at it now, I don't think keeping undo information in a
> > stack is the right thing. But keeping more than just one would be good.
> > Oh well, my first shot is never perfect. ;-)
>
> I would actually argue that
>
> git checkout -b newbranch <undo-point>
>
> is the perfect undo.
Yes, this does the job nicely. I've used it like this effectively. I
meant for undo/redo to be a lighter weight way of moving (uncommitted)
changes out of the way briefly and then replaying them onto the working
directory later.
> It leaves the old state in the old branch, and creates a new branch (and
> checks it out) with the state you want to revert to. The advantage is
> exactly that there is no "stack" of undo's: you can have multiple
> independent undo's pending, and you can continue development at any of
> them. And merge the results together.
The "stack" was the wrong thing to do. I think I would have undo pick a
name like undo-1, undo-2 etc. Or something like that. redo would pick
the most recent unless told to do otherwise.
A possible advantage of undo is having the freedom to stay on the
current branch or switch to another.
> Of course, right now we don't have a "delete branch" command, but it's
> really as simple as
>
> rm .git/refs/heads/branchname
>
> (and eventually you may want to do a "git prune" to get rid of stale
> objects, but that's a separate issue).
>
> Linus
>
This brings up a good point (indirectly). "git prune" would destroy the
undo objects. I had thought of this but decided to ignore it for the
time being.
Carl
--
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Carl Baldwin Systems VLSI Laboratory
Hewlett Packard Company
MS 88 work: 970 898-1523
3404 E. Harmony Rd. work: Carl.N.Baldwin@hp.com
Fort Collins, CO 80525 home: Carl@ecBaldwin.net
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
^ permalink raw reply
* Re: [RFC] undo and redo
From: Carl Baldwin @ 2005-08-24 20:01 UTC (permalink / raw)
To: Junio C Hamano; +Cc: Carl Baldwin, git
In-Reply-To: <7vu0hfdwql.fsf@assigned-by-dhcp.cox.net>
On Wed, Aug 24, 2005 at 11:18:42AM -0700, Junio C Hamano wrote:
> Carl Baldwin <cnb@fc.hp.com> writes:
>
> > Attached are the two scripts. Comments and criticism are welcome.
>
> An obligatory non-technical comment. I would have liked to see
> this not in a MIME multipart format, which made commenting on it
> a bit harder than necessary.
>
> > Content-Type: text/plain; charset=us-ascii
> > Content-Disposition: attachment; filename=git-undo-script
> >
> > #!/bin/sh
> >
> > . git-sh-setup-script || die "Not a git archive"
> >
> > if [ -n "$(git-diff-files)" ]; then
> > echo The following files should be updated!
> > echo
> > git-diff-files | awk '{print $6}'
> > fi
>
> There is nothing wrong with the above, but I would have written
> it like this (I think you forgot to exit after showing the list
> of files):
>
> git-update-cache --refresh || exit
I'll take this. This is what I was going for but being new to git I
didn't know all that was available. A good reason to request comments
:-)
> Also nice to learn here is "git-diff-files --name-only".
Also good to know, thanks.
Carl
--
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Carl Baldwin Systems VLSI Laboratory
Hewlett Packard Company
MS 88 work: 970 898-1523
3404 E. Harmony Rd. work: Carl.N.Baldwin@hp.com
Fort Collins, CO 80525 home: Carl@ecBaldwin.net
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
^ permalink raw reply
* RE: baffled again
From: Luck, Tony @ 2005-08-24 20:10 UTC (permalink / raw)
To: Linus Torvalds, Junio C Hamano; +Cc: git
>I think git did the "right thing", it just happened to be the thing that
>Tony didn't want. Which makes it the "wrong thing", of course, but from a
>purely technical standpoint, I don't think there's anything really wrong
>with the merge.
On the plus side ... at least it wasn't a dumb user error this time [unless
you count merging the incorrect patch in the first place, and then having
to revert it :-) ].
Could GIT be smarter here? Perhaps it could pick a few likely
ancestors and run the merge with each ... and then give some
warnings if there are files that come out differently?
-Tony
^ permalink raw reply
* Re: [RFC] undo and redo
From: Daniel Barkalow @ 2005-08-24 20:44 UTC (permalink / raw)
To: Carl Baldwin; +Cc: Linus Torvalds, git
In-Reply-To: <20050824195615.GA693@hpsvcnb.fc.hp.com>
On Wed, 24 Aug 2005, Carl Baldwin wrote:
> This brings up a good point (indirectly). "git prune" would destroy the
> undo objects. I had thought of this but decided to ignore it for the
> time being.
If you made undo store the tree under refs somewhere, git prune would
preserve it.
-Daniel
*This .sig left intentionally blank*
^ permalink raw reply
* Re: [RFC] undo and redo
From: Carl Baldwin @ 2005-08-24 20:47 UTC (permalink / raw)
To: Daniel Barkalow; +Cc: Carl Baldwin, Linus Torvalds, git
In-Reply-To: <Pine.LNX.4.63.0508241634350.23242@iabervon.org>
This is interesting. Can a ref be to a tree rather than a commit? And
it still works? I guess it would. I hadn't thought about that.
Will prune preserve any tree mentioned in any file in refs? How does
this work exactly?
Cheers,
Carl
On Wed, Aug 24, 2005 at 04:44:48PM -0400, Daniel Barkalow wrote:
> On Wed, 24 Aug 2005, Carl Baldwin wrote:
>
> > This brings up a good point (indirectly). "git prune" would destroy the
> > undo objects. I had thought of this but decided to ignore it for the
> > time being.
>
> If you made undo store the tree under refs somewhere, git prune would
> preserve it.
>
> -Daniel
> *This .sig left intentionally blank*
>
--
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Carl Baldwin Systems VLSI Laboratory
Hewlett Packard Company
MS 88 work: 970 898-1523
3404 E. Harmony Rd. work: Carl.N.Baldwin@hp.com
Fort Collins, CO 80525 home: Carl@ecBaldwin.net
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
^ permalink raw reply
* Re: [RFC] undo and redo
From: Daniel Barkalow @ 2005-08-24 21:04 UTC (permalink / raw)
To: Carl Baldwin; +Cc: Linus Torvalds, git
In-Reply-To: <20050824204736.GA13194@hpsvcnb.fc.hp.com>
On Wed, 24 Aug 2005, Carl Baldwin wrote:
> This is interesting. Can a ref be to a tree rather than a commit? And
> it still works? I guess it would. I hadn't thought about that.
Generally, each subdirectory of refs/ has refs to objects of the same
type, and heads/ is commits, but other directories are other things. tags/
is all tag objects, and you could have undo/ be trees.
> Will prune preserve any tree mentioned in any file in refs? How does
> this work exactly?
It keeps any object reachable from an object that there's a ref to in
refs.
-Daniel
*This .sig left intentionally blank*
^ permalink raw reply
* [PATCH] Audit rev-parse users again.
From: Junio C Hamano @ 2005-08-24 21:34 UTC (permalink / raw)
To: git
In-Reply-To: <Pine.LNX.4.58.0508241200500.3317@g5.osdl.org>
Some callers to rev-parse were using the output selection flags
inconsistently.
Signed-off-by: Junio C Hamano <junkio@cox.net>
---
git-bisect-script | 4 ++--
git-branch-script | 2 +-
git-log-script | 2 +-
git-request-pull-script | 4 ++--
git-revert-script | 2 +-
5 files changed, 7 insertions(+), 7 deletions(-)
ff84d327dfb8a9aa0634b0aaaca1c018cdc5117a
diff --git a/git-bisect-script b/git-bisect-script
--- a/git-bisect-script
+++ b/git-bisect-script
@@ -58,7 +58,7 @@ bisect_start() {
bisect_bad() {
bisect_autostart
case "$#" in 0 | 1) ;; *) usage ;; esac
- rev=$(git-rev-parse --revs-only --verify --default HEAD "$@") || exit
+ rev=$(git-rev-parse --verify --default HEAD "$@") || exit
echo "$rev" > "$GIT_DIR/refs/bisect/bad"
bisect_auto_next
}
@@ -67,7 +67,7 @@ bisect_good() {
bisect_autostart
case "$#" in
0) revs=$(git-rev-parse --verify HEAD) || exit ;;
- *) revs=$(git-rev-parse --revs-only "$@") || exit ;;
+ *) revs=$(git-rev-parse --revs-only --no-flags "$@") || exit ;;
esac
for rev in $revs
do
diff --git a/git-branch-script b/git-branch-script
--- a/git-branch-script
+++ b/git-branch-script
@@ -25,7 +25,7 @@ case "$#" in
head="$2^0" ;;
esac
branchname="$1"
-rev=$(git-rev-parse --revs-only --verify "$head") || exit
+rev=$(git-rev-parse --verify "$head") || exit
[ -e "$GIT_DIR/refs/heads/$branchname" ] && die "$branchname already exists"
diff --git a/git-log-script b/git-log-script
--- a/git-log-script
+++ b/git-log-script
@@ -1,4 +1,4 @@
#!/bin/sh
-revs=$(git-rev-parse --revs-only --default HEAD "$@") || exit
+revs=$(git-rev-parse --revs-only --no-flags --default HEAD "$@") || exit
[ "$revs" ] || die "No HEAD ref"
git-rev-list --pretty $(git-rev-parse --default HEAD "$@") | LESS=-S ${PAGER:-less}
diff --git a/git-request-pull-script b/git-request-pull-script
--- a/git-request-pull-script
+++ b/git-request-pull-script
@@ -19,8 +19,8 @@ head=${3-HEAD}
[ "$revision" ] || usage
[ "$url" ] || usage
-baserev=`git-rev-parse --verify $revision^0` &&
-headrev=`git-rev-parse --verify $head^0` || exit
+baserev=`git-rev-parse --verify "$revision"^0` &&
+headrev=`git-rev-parse --verify "$head"^0` || exit
echo "The following changes since commit $baserev:"
git log --max-count=1 --pretty=short "$baserev" |
diff --git a/git-revert-script b/git-revert-script
--- a/git-revert-script
+++ b/git-revert-script
@@ -10,7 +10,7 @@ case "$status" in
die "Your working tree is dirty; cannot revert a previous patch." ;;
esac
-rev=$(git-rev-parse --no-flags --verify --revs-only "$@") &&
+rev=$(git-rev-parse --verify "$@") &&
commit=$(git-rev-parse --verify "$rev^0") || exit
if git-diff-tree -R -M -p $commit | git-apply --index &&
msg=$(git-rev-list --pretty=oneline --max-count=1 $commit)
^ permalink raw reply
* [PATCH] Rationalize output selection in rev-parse.
From: Junio C Hamano @ 2005-08-24 21:40 UTC (permalink / raw)
To: git; +Cc: Linus Torvalds
In-Reply-To: <Pine.LNX.4.58.0508241200500.3317@g5.osdl.org>
Earlier rounds broke 'whatchanged -p'. In attempting to fix this,
make two axis of output selection in rev-parse orthogonal:
--revs-only tells it not to output things that are not revisions nor
flags that rev-list would take.
--no-revs tells it not to output things that are revisions or
flags that rev-list would take.
--flags tells it not to output parameters that do not start with
a '-'.
--no-flags tells it not to output parameters that starts with a '-'.
So for example 'rev-parse --no-revs -p arch/i386' would yield '-p arch/i386',
while 'rev-parse --no-revs --flags -p arch/i386' would give just '-p'.
Also the meaning of --verify has been made stronger. It now rejects
anything but a single valid rev argument. Earlier it passed some flags
through without complaining.
Signed-off-by: Junio C Hamano <junkio@cox.net>
---
Linus Torvalds <torvalds@osdl.org> writes:
> Fair enough. However, there are two kinds of flags: the
> "revision flags", and the "-p" kind of flags.
>
> And the problem was that "git-whatchanged -p" didn't work any more,
> because we passed "-p" along to "git-rev-list". Gaah.
Thanks for noticing.
rev-parse.c | 121 ++++++++++++++++++++++++++---------------------------------
1 files changed, 54 insertions(+), 67 deletions(-)
4866ccf0f434db118c4dcdeeab840eb4844d50a4
diff --git a/rev-parse.c b/rev-parse.c
--- a/rev-parse.c
+++ b/rev-parse.c
@@ -7,20 +7,21 @@
#include "commit.h"
#include "refs.h"
+#define DO_REVS 1
+#define DO_NOREV 2
+#define DO_FLAGS 4
+#define DO_NONFLAGS 8
+static int filter = ~0;
+
static char *def = NULL;
-static int no_revs = 0;
-static int single_rev = 0;
-static int revs_only = 0;
-static int do_rev_argument = 1;
-static int output_revs = 0;
-static int flags_only = 0;
-static int no_flags = 0;
-static int output_sq = 0;
-static int symbolic = 0;
#define NORMAL 0
#define REVERSED 1
static int show_type = NORMAL;
+static int symbolic = 0;
+static int output_sq = 0;
+
+static int revs_count = 0;
/*
* Some arguments are relevant "revision" arguments,
@@ -30,13 +31,19 @@ static int show_type = NORMAL;
static int is_rev_argument(const char *arg)
{
static const char *rev_args[] = {
- "--max-count=",
+ "--bisect",
+ "--header",
"--max-age=",
- "--min-age=",
+ "--max-count=",
"--merge-order",
- "--topo-order",
- "--bisect",
+ "--min-age=",
"--no-merges",
+ "--objects",
+ "--parents",
+ "--pretty",
+ "--show-breaks",
+ "--topo-order",
+ "--unpacked",
NULL
};
const char **p = rev_args;
@@ -47,11 +54,13 @@ static int is_rev_argument(const char *a
if (!str)
return 0;
len = strlen(str);
- if (!strncmp(arg, str, len))
+ if (!strcmp(arg, str) ||
+ (str[len-1] == '=' && !strncmp(arg, str, len)))
return 1;
}
}
+/* Output argument as a string, either SQ or normal */
static void show(const char *arg)
{
if (output_sq) {
@@ -70,11 +79,13 @@ static void show(const char *arg)
puts(arg);
}
+/* Output a revision, only if filter allows it */
static void show_rev(int type, const unsigned char *sha1, const char *name)
{
- if (no_revs)
+ if (!(filter & DO_REVS))
return;
- output_revs++;
+ def = NULL;
+ revs_count++;
if (type != show_type)
putchar('^');
@@ -84,29 +95,12 @@ static void show_rev(int type, const uns
show(sha1_to_hex(sha1));
}
-static void show_rev_arg(char *rev)
+/* Output a flag, only if filter allows it. */
+static void show_flag(char *arg)
{
- if (no_revs)
+ if (!(filter & DO_FLAGS))
return;
- show(rev);
-}
-
-static void show_norev(char *norev)
-{
- if (flags_only)
- return;
- if (revs_only)
- return;
- show(norev);
-}
-
-static void show_arg(char *arg)
-{
- if (no_flags)
- return;
- if (do_rev_argument && is_rev_argument(arg))
- show_rev_arg(arg);
- else
+ if (filter & (is_rev_argument(arg) ? DO_REVS : DO_NOREV))
show(arg);
}
@@ -122,7 +116,6 @@ static void show_default(void)
show_rev(NORMAL, sha1, s);
return;
}
- show_norev(s);
}
}
@@ -134,7 +127,7 @@ static int show_reference(const char *re
int main(int argc, char **argv)
{
- int i, as_is = 0;
+ int i, as_is = 0, verify = 0;
unsigned char sha1[20];
const char *prefix = setup_git_directory();
@@ -143,15 +136,13 @@ int main(int argc, char **argv)
char *dotdot;
if (as_is) {
- show_norev(arg);
+ show(arg);
continue;
}
if (*arg == '-') {
if (!strcmp(arg, "--")) {
- show_default();
- if (revs_only || flags_only)
- break;
as_is = 1;
+ continue;
}
if (!strcmp(arg, "--default")) {
def = argv[i+1];
@@ -159,25 +150,24 @@ int main(int argc, char **argv)
continue;
}
if (!strcmp(arg, "--revs-only")) {
- revs_only = 1;
+ filter &= ~DO_NOREV;
continue;
}
if (!strcmp(arg, "--no-revs")) {
- no_revs = 1;
+ filter &= ~DO_REVS;
continue;
}
if (!strcmp(arg, "--flags")) {
- flags_only = 1;
+ filter &= ~DO_NONFLAGS;
continue;
}
if (!strcmp(arg, "--no-flags")) {
- no_flags = 1;
+ filter &= ~DO_FLAGS;
continue;
}
if (!strcmp(arg, "--verify")) {
- revs_only = 1;
- do_rev_argument = 0;
- single_rev = 1;
+ filter &= ~(DO_FLAGS|DO_NOREV);
+ verify = 1;
continue;
}
if (!strcmp(arg, "--sq")) {
@@ -197,12 +187,17 @@ int main(int argc, char **argv)
continue;
}
if (!strcmp(arg, "--show-prefix")) {
- puts(prefix);
+ if (prefix)
+ puts(prefix);
continue;
}
- show_arg(arg);
+ if (verify)
+ die("Needed a single revision");
+ show_flag(arg);
continue;
}
+
+ /* Not a flag argument */
dotdot = strstr(arg, "..");
if (dotdot) {
unsigned char end[20];
@@ -212,9 +207,6 @@ int main(int argc, char **argv)
if (!*n)
n = "HEAD";
if (!get_sha1(n, end)) {
- if (no_revs)
- continue;
- def = NULL;
show_rev(NORMAL, end, n);
show_rev(REVERSED, sha1, arg);
continue;
@@ -223,26 +215,21 @@ int main(int argc, char **argv)
*dotdot = '.';
}
if (!get_sha1(arg, sha1)) {
- if (no_revs)
- continue;
- def = NULL;
show_rev(NORMAL, sha1, arg);
continue;
}
if (*arg == '^' && !get_sha1(arg+1, sha1)) {
- if (no_revs)
- continue;
- def = NULL;
show_rev(REVERSED, sha1, arg+1);
continue;
}
- show_default();
- show_norev(arg);
+ if (verify)
+ die("Needed a single revision");
+ if ((filter & (DO_NONFLAGS|DO_NOREV)) ==
+ (DO_NONFLAGS|DO_NOREV))
+ show(arg);
}
show_default();
- if (single_rev && output_revs != 1) {
- fprintf(stderr, "Needed a single revision\n");
- exit(1);
- }
+ if (verify && revs_count != 1)
+ die("Needed a single revision");
return 0;
}
^ permalink raw reply
* [PATCH] Fix "prefix" mixup in git-rev-list
From: Pavel Roskin @ 2005-08-24 21:58 UTC (permalink / raw)
To: git
Hello!
Recent changes in git have broken cg-log. git-rev-list no longer prints
"commit" in front of commit hashes. It turn out a local "prefix"
variable in main() shadows a file-scoped "prefix" variable.
The patch removed the local "prefix" variable since its value is never
used (in the intended way, that is). The call to setup_git_directory()
is kept since it has useful side effects.
The file-scoped "prefix" variable is renamed to "commit_prefix" just in
case someone reintroduces "prefix" to hold the return value of
setup_git_directory().
Signed-off-by: Pavel Roskin <proski@gnu.org>
diff --git a/rev-list.c b/rev-list.c
--- a/rev-list.c
+++ b/rev-list.c
@@ -33,7 +33,7 @@ static int blob_objects = 0;
static int verbose_header = 0;
static int show_parents = 0;
static int hdr_termination = 0;
-static const char *prefix = "";
+static const char *commit_prefix = "";
static unsigned long max_age = -1;
static unsigned long min_age = -1;
static int max_count = -1;
@@ -48,14 +48,14 @@ static void show_commit(struct commit *c
{
commit->object.flags |= SHOWN;
if (show_breaks) {
- prefix = "| ";
+ commit_prefix = "| ";
if (commit->object.flags & DISCONTINUITY) {
- prefix = "^ ";
+ commit_prefix = "^ ";
} else if (commit->object.flags & BOUNDARY) {
- prefix = "= ";
+ commit_prefix = "= ";
}
}
- printf("%s%s", prefix, sha1_to_hex(commit->object.sha1));
+ printf("%s%s", commit_prefix, sha1_to_hex(commit->object.sha1));
if (show_parents) {
struct commit_list *parents = commit->parents;
while (parents) {
@@ -481,9 +481,9 @@ static void handle_one_commit(struct com
int main(int argc, char **argv)
{
struct commit_list *list = NULL;
- const char *prefix = setup_git_directory();
int i, limited = 0;
+ setup_git_directory();
for (i = 1 ; i < argc; i++) {
int flags;
char *arg = argv[i];
@@ -511,9 +511,9 @@ int main(int argc, char **argv)
verbose_header = 1;
hdr_termination = '\n';
if (commit_format == CMIT_FMT_ONELINE)
- prefix = "";
+ commit_prefix = "";
else
- prefix = "commit ";
+ commit_prefix = "commit ";
continue;
}
if (!strncmp(arg, "--no-merges", 11)) {
--
Regards,
Pavel Roskin
^ permalink raw reply
* [PATCH] Gitk tree view (correction)
From: Ingo Bormuth @ 2005-08-24 22:35 UTC (permalink / raw)
To: git; +Cc: paulus, ingo
In-Reply-To: <20050823042432.GA21140@kruemel>
I'm sorry for sending a non-working patch. Apparently I got lost in /tmp.
So here is the patch for gitk that allows you to browse the entire tree for
every revision.
The patched gitk script and some screenshots can be found at:
http://public.efil.de/gitk/
For my personal use it's rather sufficient.
If anybody is interested in using it, I would clean it up.
- Ingo
Add tree view.
This allows you to browse the entire tree for every revision.
You may switch back an forward betweem the two modes at any time.
Keybindings: v - toggle view mode (tree/commit)
l - toggle line numbers
---
commit dbbfcc0cabb8eaaff998dc95957d73867f0e2f35
tree 53d7597f0f42ca1c3f7f01c7ca60d14541077a89
parent ccf1ee327f9a7d51704578fa41ba255abfd3a730
author <ingo@kruemel.(none)> Thu, 25 Aug 2005 00:13:22 +0200
committer <ingo@kruemel.(none)> Thu, 25 Aug 2005 00:13:22 +0200
gitk | 192 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
1 files changed, 187 insertions(+), 5 deletions(-)
diff --git a/gitk b/gitk
--- a/gitk
+++ b/gitk
@@ -329,12 +329,13 @@ proc makewindow {} {
global findtype findtypemenu findloc findstring fstring geometry
global entries sha1entry sha1string sha1but
global maincursor textcursor curtextcursor
- global rowctxmenu gaudydiff mergemax
+ global rowctxmenu gaudydiff mergemax viewmodebutton
menu .bar
.bar add cascade -label "File" -menu .bar.file
menu .bar.file
.bar.file add command -label "Reread references" -command rereadrefs
+ .bar.file add command -label "Toggle line numbers" -command togglelinenum
.bar.file add command -label "Quit" -command doquit
menu .bar.help
.bar add cascade -label "Help" -menu .bar.help
@@ -381,6 +382,9 @@ proc makewindow {} {
.ctop.top.clist add $canv3
bind .ctop.top.clist <Configure> {resizeclistpanes %W %w}
+ set viewmodebutton Tree
+ button .ctop.top.bar.viewmodebutton -textvariable viewmodebutton -command toggleviewmode
+ pack .ctop.top.bar.viewmodebutton -side left
set sha1entry .ctop.top.bar.sha1
set entries $sha1entry
set sha1but .ctop.top.bar.sha1label
@@ -493,9 +497,11 @@ proc makewindow {} {
bindkey <Key-space> "$ctext yview scroll 1 pages"
bindkey p "selnextline -1"
bindkey n "selnextline 1"
+ bindkey l "togglelinenum"
bindkey b "$ctext yview scroll -1 pages"
bindkey d "$ctext yview scroll 18 units"
bindkey u "$ctext yview scroll -18 units"
+ bindkey v "toggleviewmode"
bindkey / {findnext 1}
bindkey <Key-Return> {findnext 0}
bindkey ? findprev
@@ -2815,10 +2821,178 @@ proc gettreediffline {gdtf ids} {
lappend treediff $file
}
+proc toggleviewmode {} {
+ global treemode viewmodebutton selectedline cflist viewpath ctext
+ if { $treemode } {
+ set viewmodebutton Tree
+ set treemode false
+ } else {
+ set viewmodebutton Commit
+ set treemode true
+ }
+ # redraw
+ if {![info exists selectedline]} return
+ set l [expr $selectedline]
+ selectline $l 1
+ # select current file
+ if {! $treemode } {
+ set commitfiles [ $cflist get 0 end ]
+ set index [ lsearch $commitfiles $viewpath ]
+ if { $index > 0 } {
+ catch { after 500 $ctext yview fmark.$index }
+ }
+ }
+}
+
+proc togglelinenum {} {
+ global showlinenum selectedline
+ if { $showlinenum } { set showlinenum false } else { set showlinenum true }
+ if {![info exists selectedline]} return
+ set l [expr $selectedline]
+ selectline $l 1
+}
+
+proc viewfull { path } {
+ global ctext currentid viewpath
+ $ctext conf -state normal
+ $ctext delete 0.0 end
+
+ if { $path != "" } { set viewpath $path }
+ if { $viewpath == "Comments" || $viewpath == "/" || $viewpath == "" } {
+ set path ""
+ set viewpath "/"
+ set kind root
+ set sha $currentid
+ } else {
+ if [catch {set stream [open "|git-ls-tree $currentid $viewpath" r]}] {
+ $ctext insert end "ERROR: viewfull: git-ls-tree $currentid $viewpath"
+ return
+ }
+ gets $stream line
+ fconfigure $stream -blocking 0
+ close $stream
+ if { $line == "" } {
+ set kind "NOT FOUND !!!"
+ } else {
+ set kind [lindex $line 1]
+ }
+ set sha [lindex $line 2]
+ }
+
+ viewheader $viewpath $kind
+
+ if { $kind == "blob"} {
+ viewblob $sha
+ } elseif { $kind == "tree" || $kind == "root"} {
+ viewtree $sha
+ }
+}
+
+proc viewheader { path kind } {
+ global ctext
+ $ctext insert end "type: $kind\n"
+ $ctext insert end "path: "
+
+ set splitpath [ linsert [ split [ string trim $path "/" ] "/" ] 0 "ROOT" ]
+ set name [ lindex $splitpath end ]
+ set splitpath [ lrange $splitpath 0 end-1 ]
+ set buildpath "/"
+ foreach next $splitpath {
+ if { $next != "ROOT" } {
+ append buildpath "$next/"
+ }
+ viewprintlink "$next" $buildpath
+ $ctext insert end " / "
+ }
+ $ctext insert end "$name \n"
+ set l [expr {(78 - [string length $name]) / 2}]
+ set pad [string range "----------------------------------------" 1 $l]
+ $ctext insert end "$pad $name $pad\n" filesep
+}
+
+proc viewprintlink { name path } {
+ global ctext
+ set linkbeg [$ctext index "end - 1c"]
+ $ctext insert end "$name"
+ set linkend [$ctext index "end - 1c"]
+ $ctext tag add linkfile$name "$linkbeg + 0 c" "$linkend + 0 c"
+ $ctext tag conf linkfile$name -foreground blue -underline 1
+ $ctext tag bind linkfile$name <Enter> { %W configure -cursor hand2 }
+ $ctext tag bind linkfile$name <Leave> { %W configure -cursor $curtextcursor }
+ $ctext tag bind linkfile$name <1> [ list viewfull "$path" ]
+}
+
+
+proc viewblob {sha} {
+ global ctext linenum
+ set linenum 0
+ if [catch {set stream [open "|git-cat-file blob $sha" r]}] {
+ $ctext insert end "ERROR: viewblob"
+ return
+ }
+ fconfigure $stream -blocking 0
+ fileevent $stream readable [list getviewblobline $stream $sha]
+}
+
+proc getviewblobline {stream sha} {
+ global ctext linenum showlinenum
+ set n [gets $stream line]
+ if {$n < 0} {
+ if {![eof $stream]} return
+ close $stream
+ return
+ }
+ incr linenum
+ set num [format "%5s" "$linenum"]
+ if { $showlinenum } { $ctext insert end "$num " hunksep }
+ $ctext insert end "$line\n"
+}
+
+proc viewtree {sha} {
+ global ctext lstree
+ set lstree ""
+ $ctext insert end "\n\n"
+ if [catch {set stream [open "|git-ls-tree $sha" r]}] {
+ $ctext insert end "ERROR viewtree"
+ return
+ }
+ fconfigure $stream -blocking 0
+ fileevent $stream readable [list getviewtreeline $stream]
+}
+
+proc getviewtreeline {stream} {
+ global ctext viewpath lstree
+ set n [gets $stream line]
+ if {$n < 0} {
+ if {![eof $stream]} return
+ close $stream
+ printviewtreefilter "tree"
+ $ctext insert end "\n"
+ printviewtreefilter "blob"
+ return
+ }
+ lappend lstree $line
+}
+
+proc printviewtreefilter {filter} {
+ global ctext lstree viewpath
+ foreach line $lstree {
+ set kind [ lindex $line 1 ]
+ if { $kind != $filter} continue
+ $ctext insert end " $kind "
+ set name [ lindex $line 3 ]
+ viewprintlink $name "$viewpath/$name"
+ $ctext insert end "\n"
+ }
+}
+
proc getblobdiffs {ids} {
global diffopts blobdifffd diffids env curdifftag curtagstart
- global difffilestart nextupdate diffinhdr treediffs
-
+ global difffilestart nextupdate diffinhdr treediffs treemode
+ if { $treemode } {
+ viewfull ""
+ return
+ }
set id [lindex $ids 0]
set p [lindex $ids 1]
set env(GIT_DIFF_OPTS) $diffopts
@@ -2951,12 +3125,17 @@ proc nextfile {} {
}
proc listboxsel {} {
- global ctext cflist currentid
+ global ctext cflist currentid treemode viewpath
if {![info exists currentid]} return
set sel [lsort [$cflist curselection]]
if {$sel eq {}} return
set first [lindex $sel 0]
- catch {$ctext yview fmark.$first}
+ set viewpath [ $cflist get $first ]
+ if { $treemode } {
+ viewfull [$cflist get $first]
+ } else {
+ catch {$ctext yview fmark.$first}
+ }
}
proc setcoords {} {
@@ -3576,6 +3755,9 @@ set stopped 0
set redisplaying 0
set stuffsaved 0
set patchnum 0
+set treemode false
+set viewpath ""
+set showlinenum true
setcoords
makewindow
readrefs
--
+--------------------------------------------------------+
| Ingo Bormuth, voicebox & telefax: +49-12125-10226517 |
| GnuPG key 86326EC9 at http://ibormuth.efil.de/contact |
+--------------------------------------------------------+
^ permalink raw reply
* Re: [RFC] undo and redo
From: Junio C Hamano @ 2005-08-24 22:48 UTC (permalink / raw)
To: Daniel Barkalow; +Cc: Linus Torvalds, Carl Baldwin, git
In-Reply-To: <Pine.LNX.4.63.0508241651420.23242@iabervon.org>
Daniel Barkalow <barkalow@iabervon.org> writes:
> Generally, each subdirectory of refs/ has refs to objects of the same
> type, and heads/ is commits, but other directories are other things. tags/
> is all tag objects, and you could have undo/ be trees.
That's OK from the prune front, but I am not sure what the
ramifications of this for pulling, pushing, and resolving.
I would not recommend it without really thinking it through.
Also note that tags/ is not all tag objects. I think "git tag"
by default creates a lightweight tag, not an annotated kind.
I think you could do either one of two things. As usual, totally
untested. Just thinking aloud.
(1) A hack.
- Have a single "undo-redo" branch, which was forked from
somewhere on the "master" branch.
- When doing "undo", make a commit that has the current top
of undo-redo branch as the first parent and the current
HEAD commit as the second parent, using the tree that
represents your snapshot, to grow "undo-redo" branch.
No, this commit does *not* represent a merge, but I am
abusing the capability to record more than one parent
commits.
- When running "redo", you would want a handy way to name
what to redo. You can say "undo-redo~N" to mean "Nth
from the top of undo-redo branch.
Your implementation of "redo" can either be (patch way):
git-diff-tree -p undo-redo~N^ undo-redo~N | git apply --index
or (merge way):
git-read-tree -m undo-redo~N^2 undo-redo~N HEAD &&
git-merge-cache -o git-merge-one-file-script -a
(2) Try StGIT.
^ permalink raw reply
* Re: Tool renames? was Re: First stab at glossary
From: Junio C Hamano @ 2005-08-25 1:16 UTC (permalink / raw)
To: Tim Ottinger; +Cc: git
In-Reply-To: <430C8C31.1070902@progeny.com>
Tim Ottinger <tottinge@progeny.com> writes:
> So when this gets all settled, will we see a lot of tool renaming?
I personally do not see it coming. Any particular one you have
in mind?
^ permalink raw reply
* [ANNOUNCE] GIT 0.99.5
From: Junio C Hamano @ 2005-08-25 2:38 UTC (permalink / raw)
To: git
I've pushed out all of what has been in the proposed updates
branch, along with documentation updates.
Many changes all over:
- pulling from packed repository.
- cvsimport.
- documentation coverage.
- usability.
- terminology clarification.
- hooks for updates and commits.
- updated gitk.
- multi-head push, fetch, pull, octopus merge.
- faster merge-base.
- git from subdirectories.
- build procedure cleanups.
Have fun.
What to expect after 0.99.5
===========================
This is written in a form of to-do list for me, so if I say
"accept patch", it means I do not currently plan to do that
myself. People interested in seeing it materialize please take
a hint.
Documentation
-------------
* Accept patches from people who actually have done CVS
migration and update the cvs-migration documentation.
Link the documentation from the main git.txt page.
* Update the SubmittingPatches document to add MUA specific
hints on how to disable unwanted MIME and flowed-text by
collecting past list postings. Accept patches from people who
was hit by shiny blue bat to update the same.
* Talk about using rsync just once at the beginning when
initializing a remote repository so that local packs do not
need to be expanded. I personally do not think we need tool
support for this.
* Update tutorial to cover shared repository style a bit more,
maybe with a toy project that involves two or three
repositories.
* Update tutorial to cover setting up repository hooks to do
common tasks.
* Get help to properly use asciidoc in tutorial.
* Maybe justify and demonstrate an Octopus in the tutorial. Add
it to the glossary.
Technical (heavier)
-------------------
* Tony Luck reported an unfortunate glitch in the 3-way merge.
Encourage discussions to come up with a not-so-expensive way
to catch the kind of ambiguities that led to his misery.
Technical (milder)
------------------
* When the branch head pointed by $GIT_DIR/HEAD changes while
the index file and working tree are looking the other way
(e.g. somebody pushed into your repository, or you ran "git
fetch" to update the ref your working tree is on), "git
checkout" without -f gets confused. Figure out a good way to
handle this.
* "git commit -m" should work for initial commits and perhaps
merge commits as well. Warning about merge is still a good
thing to do, while -m is useful in scripted non-interactive
use, so we need to be careful.
* Encourage concrete proposals to commit log message templates
we discussed some time ago.
* Bug Ryan and work with him to update send-email easier to use.
* Look at portability fixes from Jason Riedy
http://www.cs.berkeley.edu/~ejr/gits/git.git#portable
* Accept patches to cause "read-tree -u" delete a directory when
it makes it empty.
* Perhaps accept patches to introduce the concept of "patch flow
expressed as ref mappings" Josef has been advocating about.
* MIMEified applymbox to grok B and Q encodings in headers and
turn them into UTF-8; unwrap QP; explode multipart.
* "git cherry-pick" that applies the patch an existing commit
introduces in its ancestry chain, possibly using the 3-way
merge machinery; update rebase using the cherry-pick command.
Carl's redo/undo might fall out naturally from this.
* A tool to detect, show and prune already merged topic
branches.
* Perhaps "git branch -d" to delete a branch.
* Enhance "git repack" to not always use --all; this would be
handy if the repository contains wagging heads like "pu" in
git.git repository.
* Remove "git clone-dumb-http".
^ permalink raw reply
* Re: [RFC] undo and redo
From: Carl Baldwin @ 2005-08-25 2:41 UTC (permalink / raw)
To: Junio C Hamano; +Cc: Daniel Barkalow, Linus Torvalds, Carl Baldwin, git
In-Reply-To: <7vd5o3ar4a.fsf@assigned-by-dhcp.cox.net>
Well, both are good ideas. Both are stack oriented, though.
I see what you mean about adding an undo directory to .git/refs/. I
will do some tests... (read further)
On Wed, Aug 24, 2005 at 03:48:21PM -0700, Junio C Hamano wrote:
> Daniel Barkalow <barkalow@iabervon.org> writes:
>
> > Generally, each subdirectory of refs/ has refs to objects of the same
> > type, and heads/ is commits, but other directories are other things. tags/
> > is all tag objects, and you could have undo/ be trees.
>
> That's OK from the prune front, but I am not sure what the
> ramifications of this for pulling, pushing, and resolving.
> I would not recommend it without really thinking it through.
So, I've tried cloning, pulling to|from, pushing to|from and resolving
merges in a repository with undo information stored under
.git/refs/undo. None of these operations seem to notice the existence
of this directory. I think this is good.
The cloned repository does not end up 'inheriting' the undo directory
(as I would expect) but does end up with any objects reachable from the
undo tree. However, these objects get pruned on the next 'git prune'.
This, I think, is minor.
Pull seems to ignore the undo directory and, of course, the objects
reachable by the undo trees. This is what I expected and wanted.
Resolving merges worked as expected.
I think undo trees should be considered local to the repository and this
is the behavior that I observed. I think this is a positive.
Before reading your message, I polished up the scripts and changed them
so that they store the undo tree and the base tree's hashes in the
.git/refs/undo directory. Also, git-redo-script can take an optional
argument...the name of the undo to replay. I guess undo should also
take an optional argument to give the undo tree some symbolic name.
I think this is getting rather solid. Let me know what you think.
Here is the git-undo-script:
#!/bin/sh
. git-sh-setup-script || die "Not a git archive"
git-update-cache --refresh || exit 1
undodir=$GIT_DIR/refs/undo
undoinfo=$undodir/$(date +%Y.%m.%d.%H.%M.%S)
headtree=$(git-cat-file commit $(cat $GIT_DIR/HEAD) | sed -n 's/^tree //p')
undotree=$(git-write-tree)
if [ $headtree == $undotree ]; then
echo There are no changes to undo.
else
mkdir -p $(dirname $undoinfo)
echo $headtree > $undoinfo.base
echo $undotree > $undoinfo.undo
echo Saved current state in $undodir as $(basename $undoinfo)
git-read-tree -m -u $undotree $headtree
fi
# --- SNIP ---
and here, is the redo script
#!/bin/sh
. git-sh-setup-script || die "Not a git archive"
git-update-cache --refresh || exit 1
usage () {
echo >&2 "Usage: git-redo-script [undo name]"
exit 1
}
undodir=$GIT_DIR/refs/undo
# If an 'undo name' was given on the command line then try to use it.
# If not, then automatically pick the most recent undo.
undoinfo=
case "$#" in
0)
undoinfo=$undodir/$(ls -tr $undodir | sed -n 's/\.undo$//p' | tail -n 1)
;;
1)
if [ -s $undodir/$1 ]; then
undoinfo=$(echo $undodir/$1 | sed -n "s/\.[^.]*$//p")
elif [ -s $undodir/$1.undo -a -s $undodir/$1.base ]; then
undoinfo=$undodir/$1
else
usage
fi
;;
*)
usage
;;
esac
# Perform a three-way merge between the base tree, undo tree and current index
if [ ! -s $undoinfo.undo -o ! -s $undoinfo.base ]; then
echo "No undo information available"
else
git-read-tree -u -m $(cat $undoinfo.base) $(cat $undoinfo.undo) $(git-write-tree)
git-merge-cache git-merge-one-file-script -a
rm -f $undoinfo.*
test -z "$(ls $undodir)" && rmdir $undodir
fi
# --- SNIP ---
I would be glad to write up documentation and provide a patch.
Cheers,
Carl
> Also note that tags/ is not all tag objects. I think "git tag"
> by default creates a lightweight tag, not an annotated kind.
>
> I think you could do either one of two things. As usual, totally
> untested. Just thinking aloud.
>
> (1) A hack.
>
> - Have a single "undo-redo" branch, which was forked from
> somewhere on the "master" branch.
>
> - When doing "undo", make a commit that has the current top
> of undo-redo branch as the first parent and the current
> HEAD commit as the second parent, using the tree that
> represents your snapshot, to grow "undo-redo" branch.
>
> No, this commit does *not* represent a merge, but I am
> abusing the capability to record more than one parent
> commits.
>
> - When running "redo", you would want a handy way to name
> what to redo. You can say "undo-redo~N" to mean "Nth
> from the top of undo-redo branch.
>
> Your implementation of "redo" can either be (patch way):
>
> git-diff-tree -p undo-redo~N^ undo-redo~N | git apply --index
>
> or (merge way):
>
> git-read-tree -m undo-redo~N^2 undo-redo~N HEAD &&
> git-merge-cache -o git-merge-one-file-script -a
>
> (2) Try StGIT.
>
>
--
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Carl Baldwin Systems VLSI Laboratory
Hewlett Packard Company
MS 88 work: 970 898-1523
3404 E. Harmony Rd. work: Carl.N.Baldwin@hp.com
Fort Collins, CO 80525 home: Carl@ecBaldwin.net
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
^ permalink raw reply
* Re: baffled again
From: Junio C Hamano @ 2005-08-25 3:26 UTC (permalink / raw)
To: Linus Torvalds; +Cc: tony.luck, git
In-Reply-To: <Pine.LNX.4.58.0508241152240.3317@g5.osdl.org>
Linus Torvalds <torvalds@osdl.org> writes:
> In fact, the case that git selected ("patch applied"), is not only the one
> that is very fundamentally the one git will always select in this kind of
> situation - in some respects is actually the nicer choice of the two.
While I appreciate the excuse for not taking immediate and hasty
action, I have two problems with your analysis.
* I am not yet convinced that it is _not_ by accident that git
ended up choosing the nicer choice of the two.
* Even if it does always choose the nicer choice of the two,
Tony was lucky (no pun intended). Rather, we were lucky that
Tony was observant. A careless merger may well have easily
missed this mismerge (from the human point of view).
^ permalink raw reply
* [RFC] Looking at multiple ancestors in merge
From: Daniel Barkalow @ 2005-08-25 3:32 UTC (permalink / raw)
To: git
I'm starting to work on letting the merging process see multiple
ancestors, and I think it's messy enough that I should actually discuss
it.
Review of the issue:
It is possible to lost reverts in cases when merging two commits with
multiple ancestors, in the following pattern: (letters representing blobs
at some filename, children to the right)
a-b-b-a-?
\ X /
a-b-b
You form a branch with unrelated changes, apply a patch in the top line,
separately merge both ways, do unrelated development in the bottom line,
and revert the patch in the top line. Then you're trying to merge the two
lines. There are two candidates for the common ancestor, the two in the
second column. If you pick the top one, you get the revert; if you pick
the bottom one, you don't. This is a bug, because it ignores the 'a'
version due to it being "unchanged", but it actually did change and
changed back.
Note that the revert is going to also be ignored if there isn't the "X" in
the middle of that diagram and the a->b change on the bottom is due to
independantly applying the same patch. Users are more likely to expect
this, however, than the situation above, where the side that is causing
the patch to be included never applied it explicitly at all; it just
merged at an unfortunate moment.
My theory is that we should handle merges by passing all of the ancestors
to read-tree, and having it use the following additions to the rules for
trivial merges:
- If any of the ancestors matches a side, don't use that side
- If you eliminate both side, don't do the trivial merge
(The first of these also means that it'll pick the best combination of
ancestors for maximizing trivial merges, as a nice side effect; the second
means that it'll avoid messing up with reverts when it has a chance of
understanding them)
If it doesn't do the trivial merge, it just puts the blob from the first
listed ancestor in stage 1, rather than trying anything fancy.
(As a further improvement, we could actually look through the history for
reasons to disregard a similarity, which would determine that there isn't
a continuous line of similarity from the recent 'a' to the common ancestor
'a', and therefore that it should be retained; but I'll be satisfied for
now with having it just not do the incorrect trivial merge.)
Of course, this is going to take a bit of work, because read-tree
currently puts all of its arguments into the cache and then works on
merging, and taking multiple ancestors requires putting them somewhere
else, because they won't fit in the cache.
-Daniel
*This .sig left intentionally blank*
^ permalink raw reply
* Re: [ANNOUNCE] GIT 0.99.5
From: Martin Langhoff @ 2005-08-25 3:30 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
In-Reply-To: <7vr7ci4u7q.fsf@assigned-by-dhcp.cox.net>
On 8/25/05, Junio C Hamano <junkio@cox.net> wrote:
> Have fun.
Yay!
> What to expect after 0.99.5
> ===========================
> Documentation
> -------------
Perhaps link the 'howto' docs from the git formal docs, so they are
visible via http://www.kernel.org/pub/software/scm/git/docs/
> * Accept patches from people who actually have done CVS
> migration and update the cvs-migration documentation.
> Link the documentation from the main git.txt page.
Yup, run trial conversions for about half a dozen cvs repos, and
currently tracking external cvs projects with git too. Will update
docs as I find time.
> * Update tutorial to cover shared repository style a bit more,
> maybe with a toy project that involves two or three
> repositories.
I recently wrote one such 'shared repo' tutorial for internal
consumption at work. Should clean it up, and add to the howto dir. The
incentive here would be to see the howtos on the web - and then I can
point people at it directly.
> Technical (milder)
> ------------------
Personally, I want to complete the Arch import. I'm interested in
feedback on the current code -- anyone has an interest in migration
from Arch or similar patch-centric SCM?
cheers,
martin
^ permalink raw reply
* Storing state in $GIT_DIR
From: Martin Langhoff @ 2005-08-25 3:32 UTC (permalink / raw)
To: GIT
Is there a convention of where/how it is safe to store additional
(non-git) data in $GIT_DIR?
The arch import needs to keep a cache with arch-commit-id =
git-commit-id mappings, and some notes about what patch-trading Arch
recorded. It'd be great to be able to store those in
$GIT_DIR/archimport/ . Is that supported?
It does not need to be replicated with push or pull, merely preserved.
cheers,
martin
^ permalink raw reply
* Re: [RFC] Looking at multiple ancestors in merge
From: A Large Angry SCM @ 2005-08-25 4:39 UTC (permalink / raw)
To: Daniel Barkalow, git
In-Reply-To: <Pine.LNX.4.63.0508242249030.23242@iabervon.org>
Daniel Barkalow wrote:
> I'm starting to work on letting the merging process see multiple
> ancestors, and I think it's messy enough that I should actually discuss
> it.
>
> Review of the issue:
>
> It is possible to lost reverts in cases when merging two commits with
> multiple ancestors, in the following pattern: (letters representing blobs
> at some filename, children to the right)
>
> a-b-b-a-?
> \ X /
> a-b-b
>
[Lots of stuff deleted]
There seems to be a lot of effort being put into auto-magically choosing
the "right" merge in the presence of multiple possible merge bases.
Unfortunately, most (all?) of the proposals are attempting to divine
intent, and so, are guaranteed to be 100% wrong at least some of the time.
Wouldn't it be better, instead, to detect that current merge being
attempted is ambiguous and require the user to specify the correct merge
base? The alternative is a tool that appears to work all of the time but
does the wrong thing some of the time.
^ permalink raw reply
* Re: [RFC] undo and redo
From: Junio C Hamano @ 2005-08-25 5:06 UTC (permalink / raw)
To: Carl Baldwin; +Cc: Daniel Barkalow, Linus Torvalds, git
In-Reply-To: <20050825024134.GA31886@hpsvcnb.fc.hp.com>
> So, I've tried cloning, pulling to|from, pushing to|from and resolving
> merges in a repository with undo information stored under
> .git/refs/undo. None of these operations seem to notice the existence
> of this directory. I think this is good.
What I meant was that, when "undo/bar" is a tree object, things
may work in a funny way:
$ git pull ../repo-with-undo/.git refs/undo/bar
$ git push ../other-repo/.git undo/bar:refs/heads/foo
$ cd ../other-repo && git resolve master foo 'Attempt to merge undo'
I think this undo/redo first needs to be thought about how best
it is used. My guess is that the workflow you have in mind is
something like this:
$ git checkout master
$ hack hack hack
# Hmph, it almost works, and but my boss says work on
# some other feature that is more urgent
$ git undo
Saved current state as 2005-08-24T20:32:22
$ work work work
$ git commit -m 'Boring but urgent fix'
# Ok, now let's back to the thing I wanted to do.
$ git redo
# I happen to know it is the last undo, so I did not name
# it, but I could have said 2005-08-24T20:32:22
$ hack more
$ git commit -m 'Finally fix frotz.'
I see some problems in this.
One is minor. As you mentioned about "giving undo a symbolic
name", after you accumulate a handful undo, you would need them
to have descriptive names, and a way to list them before using
"git redo".
But as Linus suggested in another reply, you could as well have
done this without inventing these two commands.
$ git checkout master
$ hack hack hack
# Hmph, it almost works, and but my boss says work on
# some other feature that is more urgent
$ git commit -m 'WIP - fix frotz'
$ git branch anchor-frotz
$ git reset --hard master^
$ work work work
$ git commit -m 'Boring but urgent fix'
# Ok, now let's go back to the thing I wanted to do.
$ git pull . anchor-frotz
$ rm .git/heads/anchor-frotz
$ git reset --soft master^
$ hack more
$ git commit -m 'Finally fix frotz.'
The above flow would be something somebody not so organized
(like myself) would do. A perfect person would have done this:
$ git checkout -b frotz master
$ hack hack hack
# Hmph, it almost works, and but my boss says work on
# some other feature that is more urgent
$ git commit -m 'WIP - fix frotz'
$ git checkout master
$ work work work
$ git commit -m 'Boring but urgent fix'
# Ok, now let's go back to the thing I wanted to do.
$ git checkout frotz
$ git reset --soft HEAD^
$ hack more
$ git commit -m 'Finally fix frotz.'
$ git checkout master
$ git pull . frotz
$ rm .git/refs/heads/frotz
The "perfect person" approach has an added benefit that you
could have made intermediate commits while doing "hacking",
because your hackery is always done in the "frotz" branch.
Of course, the scenarios your undo/redo is useful for may not be
limited to this "handling interrupt" use case. If that is the
only thing it solves, then I do not see much point having them
as new commands. I think the undo/redo has potential beyond
that.
So let's first clarify what kind of workflow these new commands
would help, how well that workflow is applicable in general, and
then how well these new commands would help that workflow.
> I would be glad to write up documentation and provide a patch.
Sure. I think a set of patches for new commands, and new
options to existing commands should ideally include the
following:
- Justification, such as:
- The problems new commands/options address.
- The expected workflow the new commands/options fit in.
- How useful that workflow is.
- How impossible or cumbersome to achieve that workflow using
existing tools.
Some of these should go to the commit log message, and the
documentation to describe the "best practice" workflow using
the new feature should go to Documentation/howto/ directory.
- Documentation. Files Documentation/git-*.txt to describe
new commands or updates to existing pages, new entry in
Documentation/Makefile as necessary, and a new link from
Documentation/git.txt to reach that page.
- Implementation.
- Test scripts in t/ directory, either a new test script or
updates to existing ones, if the patch is to fix existing
implementation.
^ 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