* Re: Automatic merge failed, fix up by hand
From: Linus Torvalds @ 2005-08-24 1:28 UTC (permalink / raw)
To: Junio C Hamano; +Cc: Len Brown, Git Mailing List
In-Reply-To: <7v3bp0m9ax.fsf@assigned-by-dhcp.cox.net>
On Tue, 23 Aug 2005, Junio C Hamano wrote:
>
> Only lightly tested, in the sense that I did only this one case
> and nothing else. For a large repository and with complex
> merges, "merge-base -a" _might_ end up reporting many
> candidates, in which case the pre-merge step to figure out the
> best merge base may turn out to be disastrously slow. I dunno.
Ok, I think your approach is the correct one. Just list all the commits,
and let the merge logic figure out which one is the best one.
Here, in case anybody cares, is an alternate approach, which sucks. It
_happens_ to pick the right parent in this case, but when I look at why it
picks it, it's pretty much just pure luck again. The distance function is
not good.
Just returning several entries is the correct thing to do, because then
you can make the distance function be based on the tree diffs, like you
do. That's _much_ better than trying to make the distance be based on some
topology.
So I append this patch just as a historical curiosity. Junio's patch is
clearly superior.
Linus
---
diff --git a/merge-base.c b/merge-base.c
--- a/merge-base.c
+++ b/merge-base.c
@@ -82,10 +82,84 @@ static struct commit *interesting(struct
* commit B.
*/
+/*
+ * Count the distance from one commit to the base, using a very
+ * stupid recursive algorithm. We only avoid recursion when seeing
+ * a single parent.
+ */
+static unsigned long count_distance(struct commit *head, struct commit *base)
+{
+ struct commit_list *parents;
+ unsigned long distance = ULONG_MAX;
+ unsigned long chain = 1;
+
+ /* Walk the chain of direct parents */
+ for (;;) {
+ parents = head->parents;
+ if (!parents)
+ goto no_parent;
+ /* Multiple parents? */
+ if (parents->next)
+ break;
+ head = parents->item;
+ if (head == base)
+ return chain;
+ chain++;
+ }
+
+ while (parents) {
+ struct commit *c = parents->item;
+ unsigned long d;
+
+ parents = parents->next;
+ if (c == base)
+ return chain;
+ if (c->object.flags & UNINTERESTING)
+ continue;
+ d = count_distance(c, base);
+ if (d < distance)
+ distance = d;
+ }
+ if (distance != ULONG_MAX)
+ return distance + chain;
+no_parent:
+ return ULONG_MAX;
+}
+
+/*
+ * There are some really nasty cases where we get multiple apparently
+ * equally valid parents, and we need to disambiguate them.
+ *
+ * We aim for the one whose total distance to the two revisions is the
+ * smallest, where distance is "x**2 + y**2" (we _much_ prefer a nice
+ * balanced equidistant one over one that is near to one but far from
+ * the other)
+ */
+static struct commit *pick_best_commit(struct commit_list *list, struct commit *rev1, struct commit *rev2)
+{
+ unsigned long distance = ULONG_MAX;
+ struct commit *best = NULL;
+
+ do {
+ struct commit *base = list->item;
+ unsigned long d1 = count_distance(rev1, base);
+ unsigned long d2 = count_distance(rev2, base);
+ unsigned long d = d1*d1 + d2*d2;
+
+fprintf(stderr, "distance analysis: %s: %lu %lu %lu\n", sha1_to_hex(base->object.sha1), d1, d2, d);
+ if (d < distance) {
+ distance = d;
+ best = base;
+ }
+ } while ((list = list->next) != NULL);
+ return best;
+}
+
static struct commit *common_ancestor(struct commit *rev1, struct commit *rev2)
{
struct commit_list *list = NULL;
struct commit_list *result = NULL;
+ struct commit_list *final = NULL;
if (rev1 == rev2)
return rev1;
@@ -122,7 +196,32 @@ static struct commit *common_ancestor(st
insert_by_date(p, &list);
}
}
- return interesting(result);
+
+ /*
+ * Go through the result list, and pick out unique
+ * members to put on the final list.
+ */
+ while (result) {
+ struct commit_list *entry = result;
+ struct commit *c = result->item;
+ result = result->next;
+ if (c->object.flags & UNINTERESTING)
+ continue;
+ if (c == rev1 || c == rev2)
+ return c;
+ entry->next = final;
+ final = entry;
+ c->object.flags |= UNINTERESTING;
+ }
+
+ if (!final)
+ return NULL;
+
+ /* Just one entry? */
+ if (!final->next)
+ return final->item;
+
+ return pick_best_commit(final, rev1, rev2);
}
int main(int argc, char **argv)
^ permalink raw reply
* Re: Automatic merge failed, fix up by hand
From: Len Brown @ 2005-08-24 2:25 UTC (permalink / raw)
To: Junio C Hamano; +Cc: tony.luck, Linus Torvalds, git
In-Reply-To: <7v3bp0m9ax.fsf@assigned-by-dhcp.cox.net>
On Tue, 2005-08-23 at 21:07 -0400, Junio C Hamano wrote:
> Junio C Hamano <junkio@cox.net> writes:
>
> > Probably the ideal way would be to give merge-base an option to
> > spit out all the candidates, and have the script try to see
> > which ones yield the least number of non-trivial merges.
>
> I first checked out your 702c7e.. commit, and slurped Linus tip
> (back then, 81065e2f415af6c028eac13f481fb9e60a0b487b). Then I
> ran git resolve with the attached patch (against the tip of
> git.git "master" branch). Here is what happened, which seems to
> work a little bit better, at least to me.
>
> prompt$ git checkout -f
> prompt$ git status
> nothing to commit
> prompt$ ls -l .git/HEAD
> lrwxrwxrwx 1 junio src 26 Aug 23 15:43 .git/HEAD ->
> refs/heads/lenb
> prompt$ git resolve HEAD origin 'Merge Linus into Lenb'
> Trying to find the optimum merge base
> Trying to merge 81065e2f415af6c028eac13f481fb9e60a0b487b into
> 702c7e7626deeabb057b6f529167b65ec2eefbdb using
> 3edea4833a1efcd43e1dff082bc8001fdfe74b34
Looking at gitk, it certainly chose the right ancestor in this case.
> Simple merge failed, trying Automatic merge
> Auto-merging Documentation/acpi-hotkey.txt.
> merge: warning: conflicts during merge
> ERROR: Merge conflict in Documentation/acpi-hotkey.txt.
> Auto-merging drivers/acpi/osl.c.
> fatal: merge program failed
> Automatic merge failed, fix up by hand
>
> Only lightly tested, in the sense that I did only this one case
> and nothing else. For a large repository and with complex
> merges, "merge-base -a" _might_ end up reporting many
> candidates, in which case the pre-merge step to figure out the
> best merge base may turn out to be disastrously slow. I dunno.
It ran a heck of a lot faster than the alternative -- which
would have been to export 85 patches and re-commit them
to a new tree.
Perhaps Tony's recent merge mystery had the same cause and he can also
benefit from this patch?
thanks!
-Len
^ permalink raw reply
* Fix git-rev-parse breakage
From: Linus Torvalds @ 2005-08-24 2:17 UTC (permalink / raw)
To: Junio C Hamano; +Cc: Git Mailing List
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".
[ Side note: we might want to get rid of these confusing two-way flags,
where some flags say "only print xxx", and others say "don't print yyy".
We'd be better off with just three flags that say "print zzz", where zzz
is one of "flags, revs, norevs" ]
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
---
diff --git a/rev-parse.c b/rev-parse.c
--- a/rev-parse.c
+++ b/rev-parse.c
@@ -160,6 +160,7 @@ int main(int argc, char **argv)
}
if (!strcmp(arg, "--revs-only")) {
revs_only = 1;
+ no_flags = 1;
continue;
}
if (!strcmp(arg, "--no-revs")) {
^ permalink raw reply
* Re: [RFC] Stgit - patch history / add extra parents
From: Linus Torvalds @ 2005-08-24 2:26 UTC (permalink / raw)
To: Junio C Hamano; +Cc: Catalin Marinas, git
In-Reply-To: <7virxwmbcu.fsf@assigned-by-dhcp.cox.net>
On Tue, 23 Aug 2005, Junio C Hamano wrote:
>
> Yes it can. GIT does not care if the commit ancestry does not
> make sense in contents terms (i.e. you can record one tree
> object in a commit object, and record another, completely
> unrelated tree object in a commit object that has the first
> commit object as its parent). The "git-diff-tree" output from
> comparing those two commits may not make _any_ sense at all to
> the human, though, but that is not a problem for GIT to do its
> work.
One issue is later merges.
If you have incorrect parent information, trying to do a merge may prove
impossible and/or ignore changes from the "already merged" stream. By
marking another head as a parent, you basically say "I have merged
_everything_ leading up to that other head", and if you have only actually
done a partial merge (and gotten just a part of the changes, ignoring the
others), you'll have to notice that yourself, and forward-port the rest by
hand.
For stgit, this probably doesn't matter.
Linus
^ permalink raw reply
* Re: Automatic merge failed, fix up by hand
From: Daniel Barkalow @ 2005-08-24 3:11 UTC (permalink / raw)
To: Junio C Hamano; +Cc: Len Brown, Linus Torvalds, git
In-Reply-To: <7v3bp0m9ax.fsf@assigned-by-dhcp.cox.net>
On Tue, 23 Aug 2005, Junio C Hamano wrote:
> Only lightly tested, in the sense that I did only this one case
> and nothing else. For a large repository and with complex
> merges, "merge-base -a" _might_ end up reporting many
> candidates, in which case the pre-merge step to figure out the
> best merge base may turn out to be disastrously slow. I dunno.
I think it's the right thing to do for now (and what I was going to
suggest), and if people find it too slow, we can consider teaching
read-tree to take multiple common ancestors and use any of them that gives
clear result on a per-file basis.
On the other hand, Tony might have hit a bad case with an ill-chosen
common ancestor for a patch/revert sequence, and we probably want to look
into that if we've got some history that demonstrates the problem. I think
that, if there are two common ancestors, one of which has applied a patch
and one of which hasn't, and on one side of the merge it gets reverted, we
should get the revert, but we'll only get it if we choose the ancestor
where it was applied.
(Letters are versions of the file, which 'b' being the bad patch; the
second column is the two choices for common ancestor)
a-b-a-?
/ X /
a-b-b-b
Of course, you could have the two lines exactly flipped for a different
file in the same commits, or for a different hunk in the same file, and
there would be no single choice that doesn't lose the revert. The really
right thing to do is identify that there is a b->a transition that is not
a trivial merge and that is not beyond a common ancestor, but that's hard
to determine easily and with sufficient granularity to catch everything.
I still someday want to do a version of diff/merge for git that could
select common ancestors on a per-hunk basis and identify block moves and
avoid giving confusing (but marginally shorter) diffs, but that's a major
undertaking that I don't have time for right now.
-Daniel
*This .sig left intentionally blank*
^ permalink raw reply
* Re: Fix git-rev-parse breakage
From: Junio C Hamano @ 2005-08-24 3:22 UTC (permalink / raw)
To: Linus Torvalds; +Cc: Git Mailing List
In-Reply-To: <Pine.LNX.4.58.0508231908170.3317@g5.osdl.org>
Linus Torvalds <torvalds@osdl.org> writes:
> This makes "--revs-only" imply "--no-flags".
>
> [ Side note: we might want to get rid of these confusing two-way flags,
> where some flags say "only print xxx", and others say "don't print yyy".
> We'd be better off with just three flags that say "print zzz", where zzz
> is one of "flags, revs, norevs" ]
I suspect that would not fly too well.
Being able to say "give me all flags meant for rev-list", "give
me all what are meant for rev-list", and "give me all non-flags
that are meant for rev-list" are very handy, so I'd rather want
to see --revs-only to mean "meant for rev-list", --no-revs to
mean "not meant for rev-list", --flags to mean "only ones that
start with a '-'", and --no-flags to mean "only ones that do not
start with a '-'". And that would give me (rev/no-rev/lack
thereof) x (flag/no-flag/lack thereof) = 9 combinations.
^ permalink raw reply
* Re: Automatic merge failed, fix up by hand
From: Junio C Hamano @ 2005-08-24 3:52 UTC (permalink / raw)
To: Linus Torvalds; +Cc: Len Brown, Git Mailing List
In-Reply-To: <Pine.LNX.4.58.0508231823420.3317@g5.osdl.org>
Linus Torvalds <torvalds@osdl.org> writes:
> Ok, I think your approach is the correct one. Just list all the commits,
> and let the merge logic figure out which one is the best one.
>
> Just returning several entries is the correct thing to do, because then
> you can make the distance function be based on the tree diffs, like you
> do. That's _much_ better than trying to make the distance be based on some
> topology.
>
> So I append this patch just as a historical curiosity. Junio's patch is
> clearly superior.
>
> Linus
Of course it is clearly superior, because it is not _my_ patch
but *yours*.
I just did what you earlier told the world how things should
work, based on this message:
Date: Mon, 11 Apr 2005 16:48:25 -0700 (PDT)
From: Linus Torvalds <torvalds@osdl.org>
Subject: Re: git: patch for parent-id and idea for merge
Message-ID: <Pine.LNX.4.58.0504111631360.1267@ppc970.osdl.org>
Btw, I've changed the semantics of "rev-tree" once again.
...
In other words, it will give you a way to figure out which changeset to
use as the common one. It's always going to be a parent of one of these
edge-commits that has all of its reachability bits set. Which one.. Now
that's the question. Maybe just the most recent one, or maybe actually use
"diff-tree" to see which one generates the fewest conflicts.
^ permalink raw reply
* Re: baffled again
From: Tony Luck @ 2005-08-24 5:33 UTC (permalink / raw)
To: tony.luck@intel.com; +Cc: git
In-Reply-To: <200508232256.j7NMuR1q027892@agluck-lia64.sc.intel.com>
I'm at home, and too lazy to log in to work to look at my tree. But I
have a theory
as to what went wrong for me.
At the start I had a file, same contents in test and release branch.
I applied a patch to release, and pulled to test. So the contents are still
the same, both with the patch applied.
Next, I was given a better patch (the first one just masked the real problem
and happened to make the symptoms go away). This patch touches a
completely different file. So I applied a patch to revert the change
in release,
and the new patch.
Now ... when I try to merge release into test, my guess is that GIT is
looking at the common ancestor before I touched anything. So when
it compares the current state of this file it sees that I have the bad patch
in the test tree, and the release tree has the "original" version (which has
had the patch applied and reverted ... so the contents are back at the
original state).
So GIT decides that the test branch has had a patch, and the release
branch hasn't ... and so it merges by keeping the version in test.
Plausible?
-Tony
^ permalink raw reply
* Re: baffled again
From: Linus Torvalds @ 2005-08-24 5:58 UTC (permalink / raw)
To: Tony Luck; +Cc: tony.luck@intel.com, git
In-Reply-To: <12c511ca050823223333c41857@mail.gmail.com>
On Tue, 23 Aug 2005, Tony Luck wrote:
>
> So GIT decides that the test branch has had a patch, and the release
> branch hasn't ... and so it merges by keeping the version in test.
>
> Plausible?
Very. Sounds like what happened.
Linus
^ permalink raw reply
* Re: baffled again
From: Junio C Hamano @ 2005-08-24 7:23 UTC (permalink / raw)
To: tony.luck; +Cc: git
In-Reply-To: <200508232256.j7NMuR1q027892@agluck-lia64.sc.intel.com>
tony.luck@intel.com writes:
> So I have another anomaly in my GIT tree. A patch to
> back out a bogus change to arch/ia64/hp/sim/boot/bootloader.c
> in my release branch at commit
>
> 62d75f3753647656323b0365faa43fc1a8f7be97
>
> appears to have been lost when I merged the release branch to
> the test branch at commit
>
> 0c3e091838f02c537ccab3b6e8180091080f7df2
: siamese; git cat-file commit 0c3e091838f02c537ccab3b6e8180091080f7df2
tree 61a407356d1e897e0badea552ce69e657cab6108
parent 7ffacc1a2527c219b834fe226a7a55dc67ca3637
parent a4cce10492358b33d33bb43f98284c80482037e8
author Tony Luck <tony.luck@intel.com> 1124808655 -0700
committer Tony Luck <tony.luck@intel.com> 1124808655 -0700
Pull release into test branch
So I pulled 7ffacc and a4cce1 from your repository and started
digging from there. 7ffacc was the head of "test" branch back
then, and a4cce1 was the head of "release" branch. I checked
out 7ffacc in the repository and pulled a4cce1 into it, using
the GIT with the "optimum merge-base" patch.
: siamese; git pull . aegl-release
Packing 0 objects
Unpacking 0 objects
* committish: a4cce10492358b33d33bb43f98284c80482037e8 refs/heads/aegl-release from .
Trying to find the optimum merge base.
Trying to merge a4cce10492358b33d33bb43f98284c80482037e8 into 7ffacc1a2527c219b834fe226a7a55dc67ca3637 using c1ffb910f7a4e1e79d462bb359067d97ad1a8a25.
Simple merge failed, trying Automatic merge
Auto-merging arch/ia64/sn/kernel/io_init.c.
Committed merge db376974c0aebb9e99e5cd0bce21088c6a9d927c
arch/ia64/hp/sim/boot/boot_head.S | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
It is using c1ffb9 as the merge base. The problematic path
in the three trees involved are:
: siamese; git ls-tree -r aegl-test-7ffacc1a | grep arch/ia64/hp/sim/boot/bootloader.c
100644 blob a7bed60b69f9e8de9a49944e22d03fb388ae93c7 arch/ia64/hp/sim/boot/bootloader.c
: siamese; git ls-tree -r aegl-release-a4cce1 | grep arch/ia64/hp/sim/boot/bootloader.c
100644 blob 51a7b7b4dd0e7c5720683a40637cdb79a31ec4c4 arch/ia64/hp/sim/boot/bootloader.c
: siamese; git ls-tree -r aegl-c1ffb9 | grep arch/ia64/hp/sim/boot/bootloader.c
100644 blob 51a7b7b4dd0e7c5720683a40637cdb79a31ec4c4 arch/ia64/hp/sim/boot/bootloader.c
So the file did not change between the merge base and release,
and test had the change. merge-cache picked the one in the test
release. Your guess in the other message hits the mark.
I wonder what _other_ candidates these two commits have in
common and what would have happened if they were used as the
base instead?
: siamese; git merge-base -a aegl-test-7ffacc1a aegl-release-a4cce1
f6fdd7d9c273bb2a20ab467cb57067494f932fa3
3a931d4cca1b6dabe1085cc04e909575df9219ae
c1ffb910f7a4e1e79d462bb359067d97ad1a8a25
You can check what variant of the file each of these commits
contain. What is happening is:
* the problematic patch 4aec0f is one before 3a931d. Among the
three merge-base candidates, only 3a931d contains teh wrongly
patched version.
* the problematic change 4aec0f patch introduces is part of test
branch, because it was pulled via release.
* the tip of release being merged into test has this patch
reverted, and the file is exactly the same as before 4aec0f
patch.
So three-way trivial merge algorithm says, "hey, the file did
not change between common ancestor and release but it is
different in test, so the one in the test branch must be the
merge result."
This does not have much to do with which common ancestor
merge-base chooses. Sorry, I am not sure what is the right way
to resolve this offhand.
^ permalink raw reply
* cg-clone http://www.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git fail
From: 宋冬生 @ 2005-08-24 8:01 UTC (permalink / raw)
To: git
[-- Attachment #1: Type: text/plain, Size: 1006 bytes --]
Because the rsync access method is DEPRECATED and will be REMOVED in the
future, I try the http pull method:
ab:/tmp$ cg-clone
http://www.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git
defaulting to local storage area
15:57:06
URL:http://www.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git/refs/heads/master
[41/41] -> "refs/heads/.origin-pulling" [1]
Getting pack list
Getting index for pack e3117bbaf6a59cb53c3f6f0d9b17b9433f0e4135
Getting index for pack c60dc6f7486e34043bd6861d6b2c0d21756dde76
Getting index for pack 011d837bd60b7e2544fa0f095ae4ca0d61c3c1ea
error: Couldn't get 0572e3da3ff5c3744b2f606ecf296d5f89a4bbdf: not
separate or in any pack
error: Tried
http://www.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git/objects/05/72e3da3ff5c3744b2f606ecf296d5f89a4bbdf
Cannot obtain needed object 0572e3da3ff5c3744b2f606ecf296d5f89a4bbdf
while processing commit 0000000000000000000000000000000000000000.
cg-pull: objects pull failed
cg-clone: pull failed
ab:/tmp$
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 187 bytes --]
^ permalink raw reply
* Re: cg-clone http://www.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git fail
From: 宋冬生 @ 2005-08-24 10:03 UTC (permalink / raw)
To: git
In-Reply-To: <430C294D.1060606@gmail.com>
[-- Attachment #1: Type: text/plain, Size: 2662 bytes --]
But cg-clone git.git sucess:
cg-clone http://www.kernel.org/pub/scm/linux/kernel/git/torvalds/git.git/
defaulting to local storage area
17:39:36
URL:http://www.kernel.org/pub/scm/linux/kernel/git/torvalds/git.git/refs/heads/master
[41/41] -> "refs/heads/.origin-pulling" [1]
progress: 3 objects, 5345 bytes
Getting pack list
Getting index for pack 3c5133604508466855453f3e609428f4bbba9131
Getting pack 3c5133604508466855453f3e609428f4bbba9131
which contains 6ff87c4664981e4397625791c8ea3bbb5f2279a3
progress: 1810 objects, 4197537 bytes
17:57:40
URL:http://www.kernel.org/pub/scm/linux/kernel/git/torvalds/git.git/refs/tags/v0.99
[41/41] -> "refs/tags/v0.99" [1]
17:57:41
URL:http://www.kernel.org/pub/scm/linux/kernel/git/torvalds/git.git/refs/tags/v0.99.1
[41/41] -> "refs/tags/v0.99.1" [1]
17:57:41
URL:http://www.kernel.org/pub/scm/linux/kernel/git/torvalds/git.git/refs/tags/v0.99.2
[41/41] -> "refs/tags/v0.99.2" [1]
17:57:41
URL:http://www.kernel.org/pub/scm/linux/kernel/git/torvalds/git.git/refs/tags/v0.99.3
[41/41] -> "refs/tags/v0.99.3" [1]
17:57:43
URL:http://www.kernel.org/pub/scm/linux/kernel/git/torvalds/git.git/refs/tags/v0.99.4
[41/41] -> "refs/tags/v0.99.4" [1]
FINISHED --17:57:43--
Downloaded: 5,854 bytes in 10 files
Missing object of tag v0.99.1... retrieved
Missing object of tag v0.99.2... retrieved
Missing object of tag v0.99.3... retrieved
Missing object of tag v0.99.4... retrieved
New branch: 2a29da7c6d6103c4719c71f6cce88e853260912c
Cloned to git/ (origin
http://www.kernel.org/pub/scm/linux/kernel/git/torvalds/git.git
available as branch "origin")
May be linux-2.6.git something wrong?
>Because the rsync access method is DEPRECATED and will be REMOVED in the
>future, I try the http pull method:
>
>ab:/tmp$ cg-clone
>http://www.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git
>defaulting to local storage area
>15:57:06
>URL:http://www.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git/refs/heads/master
>[41/41] -> "refs/heads/.origin-pulling" [1]
>Getting pack list
>Getting index for pack e3117bbaf6a59cb53c3f6f0d9b17b9433f0e4135
>Getting index for pack c60dc6f7486e34043bd6861d6b2c0d21756dde76
>Getting index for pack 011d837bd60b7e2544fa0f095ae4ca0d61c3c1ea
>error: Couldn't get 0572e3da3ff5c3744b2f606ecf296d5f89a4bbdf: not
>separate or in any pack
>error: Tried
>http://www.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git/objects/05/72e3da3ff5c3744b2f606ecf296d5f89a4bbdf
>Cannot obtain needed object 0572e3da3ff5c3744b2f606ecf296d5f89a4bbdf
>while processing commit 0000000000000000000000000000000000000000.
>cg-pull: objects pull failed
>cg-clone: pull failed
>ab:/tmp$
>
>
>
>
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 187 bytes --]
^ permalink raw reply
* git-archimport-script - 2nd iteration
From: Martin Langhoff @ 2005-08-24 12:14 UTC (permalink / raw)
To: GIT
[-- Attachment #1: Type: text/plain, Size: 492 bytes --]
Gave the code another pass. The code should be more readable, and make
a bit more sense.
It now:
- handles commit timestamps correctly
- handles binary files correctly
- uses parselog() to tell git-update-cache what's been
added/deleted/modified - much faster commits on large trees
- gets the commit msgs mostly ok
In my immediate TODO:
- handling renames
- branches
- incremental import
A bit further off:
- file modes
- merge detection
cheers,
martin
[-- Attachment #2: git-archimport-script --]
[-- Type: application/octet-stream, Size: 11396 bytes --]
#!/usr/bin/perl -w
# This tool is copyright (c) 2005, Matthias Urlichs.
# It is released under the Gnu Public License, version 2.
#
# The basic idea is to walk the output of tla abrowse,
# fetch the changesets and apply them.
#
=head1 Devel tricks
Add print in front of the shell commands invoked via backticks.
=head2 TODO
- deal with renames correctly
- deal with branches correctly
- keep track of merged patches, and mark a git merge when it happens
- smarter rules to parse the archive history "up" and "down"
- be able to continue an import where we left off
=cut
use strict;
use warnings;
use Getopt::Std;
use File::Spec;
use File::Temp qw(tempfile);
use File::Path qw(mkpath);
use File::Basename qw(basename dirname);
use String::ShellQuote;
use Time::Local;
use IO::Socket;
use IO::Pipe;
use POSIX qw(strftime dup2);
use Data::Dumper qw/ Dumper /;
use IPC::Open2;
$SIG{'PIPE'}="IGNORE";
$ENV{'TZ'}="UTC";
our($opt_h,$opt_A,$opt_v,$opt_k,
$opt_d,$opt_p,$opt_C,$opt_z,
$opt_i,$opt_t);
sub usage() {
print STDERR <<END;
Usage: ${\basename $0} # fetch/update GIT from Arch
[ -h ] [ -v ] [ -A archive ]
[ -C GIT_repository ] [ -t tempdir ]
[ arch-branch ]
END
exit(1);
}
getopts("hviA:C:t:") or usage();
usage if $opt_h;
@ARGV <= 1 or usage();
my $tmp = $opt_t;
$tmp ||= '/tmp';
$tmp .= '/git-archimport/';
my $git_tree = $opt_C;
$git_tree ||= ".";
my $arch_branch = '';
if ($#ARGV == 0) {
$arch_branch = $ARGV[0];
}
# TODO: handle more than one repo
open ABROWSE, "tla abrowse -f -A $opt_A --desc --merges $arch_branch |"
or die "Problems with tla abrowse: $!";
my @psets = (); # the collection
my %ps = (); # the current one
my $mode = '';
my $lastseen = '';
while (<ABROWSE>) {
chomp;
# first record padded w 8 spaces
if (s/^\s{8}\b//) {
# store the record we just captured
if (%ps) {
my %temp = %ps; # break references
push (@psets, \%temp);
%ps = ();
}
my ($id, $type) = split(m/\s{3}/, $_);
$ps{id} = $id;
# deal with types
if ($type =~ m/^\(simple changeset\)/) {
$ps{type} = 's';
} elsif ($type eq '(initial import)') {
$ps{type} = 'i';
} elsif ($type =~ m/^\(tag revision of (.+)\)/) {
$ps{type} = 't';
$ps{tag} = $1;
} else {
warn "Unknown type $type";
}
$lastseen = 'id';
}
if (s/^\s{10}//) {
# 10 leading spaces or more
# indicate commit metadata
# date & author
if ($lastseen eq 'id' && m/^\d{4}-\d{2}-\d{2}/) {
my ($date, $authoremail) = split(m/\s{2,}/, $_);
$ps{date} = $date;
$ps{date} =~ s/\bGMT$//; # strip off trailign GMT
if ($ps{date} =~ m/\b\w+$/) {
warn 'Arch dates not in GMT?! - imported dates will be wrong';
}
$authoremail =~ m/^(.+)\s(\S+)$/;
$ps{author} = $1;
$ps{email} = $2;
$lastseen = 'date';
} elsif ($lastseen eq 'date') {
# the only hint is position
# subject is after date
$ps{subj} = $_;
$lastseen = 'subj';
} elsif ($lastseen eq 'subj' && $_ eq 'merges in:') {
$ps{merges} = [];
$lastseen = 'merges';
} elsif ($lastseen eq 'merges' && s/^\s{2}//) {
push (@{$ps{merges}}, $_);
} else {
warn 'more metadata after merges!?';
}
}
}
if (%ps) {
my %temp = %ps; # break references
push (@psets, \%temp);
%ps = ();
}
close ABROWSE;
## Order patches by time
@psets = sort {$a->{date}.$b->{id} cmp $b->{date}.$b->{id}} @psets;
#print Dumper \@psets;
##
## TODO cleanup irrelevant patches
## and put an initial import
## or a full tag
if ($opt_i) { # initial import
if ($psets[0]{type} eq 'i' || $psets[0]{type} eq 't') {
print "Starting import from $psets[0]{id}\n";
} else {
die "Need to start from an import or a tag -- cannot use $psets[0]{id}";
}
`git-init-db`;
die $! if $?;
}
# process
my $lastbranch = branchname($psets[0]{id}); # only good for initial import
foreach my $ps (@psets) {
$ps->{branch} = branchname($ps->{id});
#
# ensure we have a clean state
#
if (`git diff-files`){
die "Unclean tree when about to process $ps->{id} " .
" - did we fail to commit cleanly before?";
}
die $! if $?;
#
# create the branch if needed
# TODO: Find the ancestor!
#
unless ( -e ".git/refs/heads/$ps->{branch}") {
`git checkout -b $ps->{branch}`;
} else {
`git checkout $ps->{branch}`;
}
die $! if $?;
#
# Apply the import/changeset/merge into the working tree
#
if ($ps->{type} eq 'i') {
apply_import($ps) or die $!;
} elsif ($ps->{type} eq 's') {
apply_cset($ps);
}
#
# prepare update git's index, based on what arch knows
# about the pset, resolve parents, etc
#
my $tree;
my $commitlog = `tla cat-archive-log -A $opt_A $ps->{id}`;
die "Error in cat-archive-log: $!" if $?;
# parselog will git-add/rm files
# and generally prepare things for the commit
# NOTE: parselog will shell-quote filenames!
my ($sum, $msg, $add, $del, $mod) = parselog($commitlog);
my $logmessage = "$sum\n$msg";
# imports don't give us good info
# on added files. Shame on them
if ($ps->{type} eq 'i'){
`find . -type f -print0 | grep -zv '^./.git' | xargs -0 git-update-cache --add`;
}
if (@$add) {
$add = join(' ', @$add);
`git-update-cache --add $add`;
die "Error in git-update-cache --add: $!" if $?;
}
if (@$del) {
foreach my $file (@$del) {
unlink $file or die "Problems deleting $file : $!";
}
$del = join (' ', @$del);
`git-update-cache --remove $del`;
die "Error in git-update-cache --remove: $!" if $?;
}
if (@$mod) {
$mod = join (' ', @$mod);
`git-update-cache $mod`;
die "Error in git-update-cache: $!" if $?;
}
# warn "errors when runnign git-update-cache! $!";
$tree = `git-write-tree`;
die "cannot write tree $!" if $?;
chomp $tree;
#
# Commit and clean state
#
my @par;
if ( -e ".git/refs/heads/$ps->{branch}"){
if (open HEAD, "<.git/refs/heads/$ps->{branch}") {
my $p = <HEAD>;
close HEAD;
chomp $p;
push @par, '-p', $p;
} else {
if ($ps->{type} eq 's') {
warn "Could not find the right head for the branch $ps->{branch}";
}
}
}
my $par = join (' ', @par);
$ENV{TZ} = 'GMT';
$ENV{GIT_AUTHOR_NAME} = $ps->{author};
$ENV{GIT_AUTHOR_EMAIL} = $ps->{email};
$ENV{GIT_AUTHOR_DATE} = $ps->{date};
$ENV{GIT_COMMITTER_NAME} = $ps->{author};
$ENV{GIT_COMMITTER_EMAIL} = $ps->{email};
$ENV{GIT_COMMITTER_DATE} = $ps->{date};
print "\t+ commit date is $ps->{date} \n";
my ($pid, $commit_rh, $commit_wh);
$commit_rh = 'commit_rh';
$commit_wh = 'commit_wh';
$pid = open2(*READER, *WRITER, "git-commit-tree $tree $par")
or die $!;
print WRITER $logmessage; # write
close WRITER;
my $commitid = <READER>; # read
chomp $commitid;
close READER;
waitpid $pid,0; # close;
if (length $commitid != 40) {
die "Something went wrong with the commit! $! $commitid";
}
#
# Update the branch
#
open HEAD, ">.git/refs/heads/$ps->{branch}";
print HEAD $commitid;
close HEAD;
unlink ('.git/HEAD');
symlink("refs/heads/$ps->{branch}",".git/HEAD");
print " * Committed $ps->{id}\n";
print " + tree $tree\n";
print " + commit $commitid\n";
}
sub branchname {
my $id = shift;
$id =~ s#^.+?/##;
my @parts = split(m/--/, $id);
return join('--', @parts[0..1]);
}
sub apply_import {
my $ps = shift;
my $bname = branchname($ps->{id});
`mkdir -p $tmp`;
`tla get -s --no-pristine -A $opt_A $ps->{id} $tmp/import`;
die "Cannot get import: $!" if $?;
`rsync -v --archive --delete --exclude '.git' --exclude '.arch-ids' --exclude '{arch}' $tmp/import/* ./`;
die "Cannot rsync import:$!" if $?;
`rm -fr $tmp/import`;
die "Cannot remove tempdir: $!" if $?;
return 1;
}
sub apply_cset {
my $ps = shift;
`mkdir -p $tmp`;
# get the changeset
`tla get-changeset -A $opt_A $ps->{id} $tmp/changeset`;
die "Cannot get changeset: $!" if $?;
# apply patches
if (`find $tmp/changeset/patches -type f -name '*.patch'`) {
# this can be sped up considerably by doing
# (find | xargs cat) | patch
# but that cna get mucked up by patches
# with missing trailing newlines or the standard
# 'missing newline' flag in the patch - possibly
# produced with an old/buggy diff.
# slow and safe, we invoke patch once per patchfile
`find $tmp/changeset/patches -type f -name '*.patch' -print0 | grep -zv '{arch}' | xargs -iFILE -0 --no-run-if-empty patch -p1 --forward -iFILE`;
die "Problem applying patches! $!" if $?;
}
# apply changed binary files
if (my @modified = `find $tmp/changeset/patches -type f -name '*.modified'`) {
foreach my $mod (@modified) {
chomp $mod;
my $orig = $mod;
$orig =~ s/\.modified$//; # lazy
$orig =~ s!^\Q$tmp\E/changeset/patches/!!;
print "rsync -p '$mod' '$orig'";
`rsync -p $mod ./$orig`;
die "Problem applying binary changes! $!" if $?;
}
}
# bring in new files
`rsync --archive --exclude '.git' --exclude '.arch-ids' --exclude '{arch}' $tmp/changeset/new-files-archive/* ./`;
# deleted files are hinted from the commitlog processing
`rm -fr $tmp/changeset`;
}
# =for reference
# A log entry looks like
# Revision: moodle-org--moodle--1.3.3--patch-15
# Archive: arch-eduforge@catalyst.net.nz--2004
# Creator: Penny Leach <penny@catalyst.net.nz>
# Date: Wed May 25 14:15:34 NZST 2005
# Standard-date: 2005-05-25 02:15:34 GMT
# New-files: lang/de/.arch-ids/block_glossary_random.php.id
# lang/de/.arch-ids/block_html.php.id
# New-directories: lang/de/help/questionnaire
# lang/de/help/questionnaire/.arch-ids
# Removed-files: lang/be/docs/.arch-ids/release.html.id
# lang/be/docs/.arch-ids/releaseold.html.id
# Modified-files: admin/cron.php admin/delete.php
# admin/editor.html backup/lib.php backup/restore.php
# New-patches: arch-eduforge@catalyst.net.nz--2004/moodle-org--moodle--1.3.3--patch-15
# Summary: Updating to latest from MOODLE_14_STABLE (1.4.5+)
# Keywords:
#
# Updating yadda tadda tadda madda
sub parselog {
my $log = shift;
print $log;
my (@add, @del, @mod, @kw, $sum, $msg );
if ($log =~ m/(?:\n|^)New-files:(.*?)(?=\n\w)/s ) {
my $files = $1;
@add = split(m/\s+/s, $files);
}
if ($log =~ m/(?:\n|^)Removed-files:(.*?)(?=\n\w)/s ) {
my $files = $1;
@del = split(m/\s+/s, $files);
}
if ($log =~ m/(?:\n|^)Modified-files:(.*?)(?=\n\w)/s ) {
my $files = $1;
@mod = split(m/\s+/s, $files);
}
if ($log =~ m/^Summary:(.+?)$/m ) {
$sum = $1;
$sum =~ s/^\s+//;
$sum =~ s/\s+$//;
}
if ($log =~ m/\n\n(.+)$/s) {
$msg = $1;
$msg =~ s/^\s+//;
$msg =~ s/\s+$//;
}
# cleanup the arrays
foreach my $ref ( (\@add, \@del, \@mod) ) {
my @tmp = ();
while (my $t = pop @$ref) {
next unless length ($t);
next if $t =~ m!\{arch\}/!;
next if $t =~ m!\.arch-ids/!;
push (@tmp, shell_quote($t));
}
@$ref = @tmp;
}
print Dumper [$sum, $msg, \@add, \@del, \@mod];
return ($sum, $msg, \@add, \@del, \@mod);
}
^ permalink raw reply
* Tool renames? was Re: First stab at glossary
From: Tim Ottinger @ 2005-08-24 15:03 UTC (permalink / raw)
To: git
In-Reply-To: <Pine.LNX.4.63.0508180009180.18104@wgmdd8.biozentrum.uni-wuerzburg.de>
So when this gets all settled, will we see a lot of tool renaming?
While it would cause me and my team some personal effort (we have
a special-purpose porcelain), it would be welcome to have a lexicon
that is sane and consistent, and in tune with all the documentation.
Others may feel differently, I understand.
--
><>
... either 'way ahead of the game, or 'way out in left field.
^ permalink raw reply
* Re: baffled again
From: Daniel Barkalow @ 2005-08-24 16:09 UTC (permalink / raw)
To: Junio C Hamano; +Cc: tony.luck, git
In-Reply-To: <7vek8jhk7y.fsf@assigned-by-dhcp.cox.net>
On Wed, 24 Aug 2005, Junio C Hamano wrote:
> tony.luck@intel.com writes:
>
> > So I have another anomaly in my GIT tree. A patch to
> > back out a bogus change to arch/ia64/hp/sim/boot/bootloader.c
> > in my release branch at commit
> >
> > 62d75f3753647656323b0365faa43fc1a8f7be97
> >
> > appears to have been lost when I merged the release branch to
> > the test branch at commit
> >
> > 0c3e091838f02c537ccab3b6e8180091080f7df2
>
> : siamese; git cat-file commit 0c3e091838f02c537ccab3b6e8180091080f7df2
> tree 61a407356d1e897e0badea552ce69e657cab6108
> parent 7ffacc1a2527c219b834fe226a7a55dc67ca3637
> parent a4cce10492358b33d33bb43f98284c80482037e8
> author Tony Luck <tony.luck@intel.com> 1124808655 -0700
> committer Tony Luck <tony.luck@intel.com> 1124808655 -0700
>
> Pull release into test branch
>
> So I pulled 7ffacc and a4cce1 from your repository and started
> digging from there. 7ffacc was the head of "test" branch back
> then, and a4cce1 was the head of "release" branch. I checked
> out 7ffacc in the repository and pulled a4cce1 into it, using
> the GIT with the "optimum merge-base" patch.
>
> : siamese; git pull . aegl-release
> Packing 0 objects
> Unpacking 0 objects
>
> * committish: a4cce10492358b33d33bb43f98284c80482037e8 refs/heads/aegl-release from .
> Trying to find the optimum merge base.
> Trying to merge a4cce10492358b33d33bb43f98284c80482037e8 into 7ffacc1a2527c219b834fe226a7a55dc67ca3637 using c1ffb910f7a4e1e79d462bb359067d97ad1a8a25.
> Simple merge failed, trying Automatic merge
> Auto-merging arch/ia64/sn/kernel/io_init.c.
> Committed merge db376974c0aebb9e99e5cd0bce21088c6a9d927c
> arch/ia64/hp/sim/boot/boot_head.S | 2 +-
> 1 files changed, 1 insertions(+), 1 deletions(-)
>
> It is using c1ffb9 as the merge base. The problematic path
> in the three trees involved are:
>
> : siamese; git ls-tree -r aegl-test-7ffacc1a | grep arch/ia64/hp/sim/boot/bootloader.c
> 100644 blob a7bed60b69f9e8de9a49944e22d03fb388ae93c7 arch/ia64/hp/sim/boot/bootloader.c
> : siamese; git ls-tree -r aegl-release-a4cce1 | grep arch/ia64/hp/sim/boot/bootloader.c
> 100644 blob 51a7b7b4dd0e7c5720683a40637cdb79a31ec4c4 arch/ia64/hp/sim/boot/bootloader.c
> : siamese; git ls-tree -r aegl-c1ffb9 | grep arch/ia64/hp/sim/boot/bootloader.c
> 100644 blob 51a7b7b4dd0e7c5720683a40637cdb79a31ec4c4 arch/ia64/hp/sim/boot/bootloader.c
>
> So the file did not change between the merge base and release,
> and test had the change. merge-cache picked the one in the test
> release. Your guess in the other message hits the mark.
>
> I wonder what _other_ candidates these two commits have in
> common and what would have happened if they were used as the
> base instead?
>
> : siamese; git merge-base -a aegl-test-7ffacc1a aegl-release-a4cce1
> f6fdd7d9c273bb2a20ab467cb57067494f932fa3
> 3a931d4cca1b6dabe1085cc04e909575df9219ae
> c1ffb910f7a4e1e79d462bb359067d97ad1a8a25
>
> You can check what variant of the file each of these commits
> contain.
>
> What is happening is:
>
> * the problematic patch 4aec0f is one before 3a931d. Among the
> three merge-base candidates, only 3a931d contains teh wrongly
> patched version.
>
> * the problematic change 4aec0f patch introduces is part of test
> branch, because it was pulled via release.
>
> * the tip of release being merged into test has this patch
> reverted, and the file is exactly the same as before 4aec0f
> patch.
>
> So three-way trivial merge algorithm says, "hey, the file did
> not change between common ancestor and release but it is
> different in test, so the one in the test branch must be the
> merge result."
>
> This does not have much to do with which common ancestor
> merge-base chooses. Sorry, I am not sure what is the right way
> to resolve this offhand.
If it picks 3a931d4cca1b6dabe1085cc04e909575df9219ae, it will determine
that the file didn't change between that and test, and is different in
release, so the one in release must be right. I believe that the hint that
something is going on is that different common ancestors give
different trivial merges (as opposed to some giving failure and some
giving the same result), and resolving it probably involves identifying
that that paths from f6f... and c1f... to release don't keep the same blob
through the middle, despite having the same ends.
-Daniel
*This .sig left intentionally blank*
^ permalink raw reply
* Query about status of http-pull
From: Martin Schlemmer @ 2005-08-24 16:10 UTC (permalink / raw)
To: GIT Mailing Lists
[-- Attachment #1: Type: text/plain, Size: 1344 bytes --]
Hi,
Recently cogito again say that the rsync method will be deprecated in
future (due to http-pull now supporting pack objects I suppose), but it
seems to me that it still have other issues:
-----
lycan linux-2.6 # git pull origin
Fetching HEAD using http
Getting pack list
error: Couldn't get 0572e3da3ff5c3744b2f606ecf296d5f89a4bbdf: not separate or in any pack
error: Tried http://www.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git/objects/05/72e3da3ff5c3744b2f606ecf296d5f89a4bbdf
Cannot obtain needed object 0572e3da3ff5c3744b2f606ecf296d5f89a4bbdf
while processing commit 0000000000000000000000000000000000000000.
lycan linux-2.6 # cg-update
17:50:02 URL:http://www.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git/refs/heads/master [41/41] -> "refs/heads/.origin-pulling" [1]
FINISHED --17:50:09--
Downloaded: 11,949 bytes in 5 files
Missing object of tag v2.6.13-rc7... unable to retrieve
Up to date.
Applying changes...
Branch already fully merged.
lycan linux-2.6 #
-----
If you switch it however to rsync again, it works just fine. Other
branches like that of KLIBC and one or two others do not even pull via
http-pull.
So basically the question is if this is known issues (had mail issues,
so missed the last week or so's mail) ?
Thanks,
--
Martin Schlemmer
[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 189 bytes --]
^ permalink raw reply
* Re: Query about status of http-pull
From: Daniel Barkalow @ 2005-08-24 16:39 UTC (permalink / raw)
To: Martin Schlemmer; +Cc: GIT Mailing Lists, Linus Torvalds
In-Reply-To: <1124899847.7187.18.camel@lycan.lan>
On Wed, 24 Aug 2005, Martin Schlemmer wrote:
> Hi,
>
> Recently cogito again say that the rsync method will be deprecated in
> future (due to http-pull now supporting pack objects I suppose), but it
> seems to me that it still have other issues:
>
> -----
> lycan linux-2.6 # git pull origin
> Fetching HEAD using http
> Getting pack list
> error: Couldn't get 0572e3da3ff5c3744b2f606ecf296d5f89a4bbdf: not separate or in any pack
> error: Tried http://www.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git/objects/05/72e3da3ff5c3744b2f606ecf296d5f89a4bbdf
> Cannot obtain needed object 0572e3da3ff5c3744b2f606ecf296d5f89a4bbdf
> while processing commit 0000000000000000000000000000000000000000.
It looks like pack-c24bb5025e835a3d8733931ce7cc440f7bfbaaed isn't in the
pack list. I suspect that updating this file should really be done by
anything that creates pack files, because people forget to run the program
that does it otherwise and then http has problems.
-Daniel
*This .sig left intentionally blank*
^ permalink raw reply
* [RFC] undo and redo
From: Carl Baldwin @ 2005-08-24 17:23 UTC (permalink / raw)
To: git
[-- Attachment #1: Type: text/plain, Size: 1408 bytes --]
Hello,
So, one thing that I liked about GNU Arch when I tried it out was the
ability to undo and redo changes in the local working copy. I decided
to try to do this with git. What I have is preliminary. I'm sure it
could use some work.
So, I started with the assumption that all changes in the working copy
have been updated to the cache. My scripts check this (with
git-diff-files) and abort if this is not the case.
Undo calls git-write-tree to write the changes to the object store. It
stores that tree's hash and the current HEAD's tree's hash in a file.
Then it reverts the working copy to HEAD.
Redo grabs these two trees from the file, does git-write-tree to produce
a third tree and merges the three using the old HEAD's tree as the base
of the merge. This way, new commits can happen and the local copy can
be modified since the undo and it should still work assuming no
conflicts emerge.
Attached are the two scripts. Comments and criticism are welcome.
Cheers,
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
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
[-- Attachment #2: git-redo-script --]
[-- Type: text/plain, Size: 675 bytes --]
#!/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
undostack=$GIT_DIR/undostack
if [ ! -s $undostack ]; then
echo "No undo information in $undostack"
else
# Read the top of the stack
basetree=$(cat $undostack | tail -n 2 | head -n 1)
redotree=$(cat $undostack | tail -n 1)
# Pop the stack
cat $undostack | head -n -2 > $undostack.tmp
mv $undostack{.tmp,}
currenttree=$(git-write-tree)
git-read-tree -u -m $basetree $currenttree $redotree
git-merge-cache git-merge-one-file-script -a
fi
[-- Attachment #3: git-undo-script --]
[-- Type: text/plain, Size: 611 bytes --]
#!/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
undostack=$GIT_DIR/undostack
headtree=$(git-cat-file commit $(cat $GIT_DIR/HEAD) | head -n 1 | sed -e 's/tree //')
undotree=$(git-write-tree)
if [ $headtree == $undotree ]; then
echo There are no changes to undo.
else
{
echo $headtree
echo $undotree
} >> $undostack
echo Saved current state as tree $undotree.
echo Reverting to HEAD, $headtree...
git-checkout-script -f
fi
^ permalink raw reply
* Re: [RFC] undo and redo
From: Carl Baldwin @ 2005-08-24 18:10 UTC (permalink / raw)
To: Carl Baldwin; +Cc: git
In-Reply-To: <20050824172339.GA7083@hpsvcnb.fc.hp.com>
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. ;-)
Carl
On Wed, Aug 24, 2005 at 11:23:39AM -0600, Carl Baldwin wrote:
> Hello,
>
> So, one thing that I liked about GNU Arch when I tried it out was the
> ability to undo and redo changes in the local working copy. I decided
> to try to do this with git. What I have is preliminary. I'm sure it
> could use some work.
>
> So, I started with the assumption that all changes in the working copy
> have been updated to the cache. My scripts check this (with
> git-diff-files) and abort if this is not the case.
>
> Undo calls git-write-tree to write the changes to the object store. It
> stores that tree's hash and the current HEAD's tree's hash in a file.
> Then it reverts the working copy to HEAD.
>
> Redo grabs these two trees from the file, does git-write-tree to produce
> a third tree and merges the three using the old HEAD's tree as the base
> of the merge. This way, new commits can happen and the local copy can
> be modified since the undo and it should still work assuming no
> conflicts emerge.
>
> Attached are the two scripts. Comments and criticism are welcome.
>
> Cheers,
> 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
> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
> #!/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
>
> undostack=$GIT_DIR/undostack
>
> if [ ! -s $undostack ]; then
> echo "No undo information in $undostack"
> else
> # Read the top of the stack
> basetree=$(cat $undostack | tail -n 2 | head -n 1)
> redotree=$(cat $undostack | tail -n 1)
>
> # Pop the stack
> cat $undostack | head -n -2 > $undostack.tmp
> mv $undostack{.tmp,}
>
> currenttree=$(git-write-tree)
>
> git-read-tree -u -m $basetree $currenttree $redotree
> git-merge-cache git-merge-one-file-script -a
> fi
> #!/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
>
> undostack=$GIT_DIR/undostack
>
> headtree=$(git-cat-file commit $(cat $GIT_DIR/HEAD) | head -n 1 | sed -e 's/tree //')
> undotree=$(git-write-tree)
>
> if [ $headtree == $undotree ]; then
> echo There are no changes to undo.
> else
> {
> echo $headtree
> echo $undotree
> } >> $undostack
>
> echo Saved current state as tree $undotree.
> echo Reverting to HEAD, $headtree...
>
> git-checkout-script -f
> fi
--
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
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: Query about status of http-pull
From: Junio C Hamano @ 2005-08-24 18:16 UTC (permalink / raw)
To: Daniel Barkalow; +Cc: git, Linus Torvalds
In-Reply-To: <Pine.LNX.4.63.0508241233260.23242@iabervon.org>
Daniel Barkalow <barkalow@iabervon.org> writes:
> It looks like pack-c24bb5025e835a3d8733931ce7cc440f7bfbaaed isn't in the
> pack list. I suspect that updating this file should really be done by
> anything that creates pack files, because people forget to run the program
> that does it otherwise and then http has problems.
True.
Added at the end of git-repack-script (Linus can disable it by
giving an '-n' flag when packing his private repositories).
^ permalink raw reply
* Re: [RFC] undo and redo
From: Junio C Hamano @ 2005-08-24 18:18 UTC (permalink / raw)
To: Carl Baldwin; +Cc: git
In-Reply-To: <20050824172339.GA7083@hpsvcnb.fc.hp.com>
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
Also nice to learn here is "git-diff-files --name-only".
> Content-Type: text/plain; charset=us-ascii
> Content-Disposition: attachment; filename=git-redo-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
Same here.
> currenttree=$(git-write-tree)
> git-read-tree -u -m $basetree $currenttree $redotree
> git-merge-cache git-merge-one-file-script -a
Interesting. Very interesting.
^ permalink raw reply
* Re: Query about status of http-pull
From: Linus Torvalds @ 2005-08-24 18:25 UTC (permalink / raw)
To: Junio C Hamano; +Cc: Daniel Barkalow, git
In-Reply-To: <7v1x4jfbdy.fsf@assigned-by-dhcp.cox.net>
On Wed, 24 Aug 2005, Junio C Hamano wrote:
>
> Added at the end of git-repack-script (Linus can disable it by
> giving an '-n' flag when packing his private repositories).
No, I just haven't updated my git on master.kernel.org in a while. So
nothing to disable.
I ran git-update-server-info manually, so it should work now.
Linus
^ permalink raw reply
* Re: [PATCH] Introduce "reset type" flag to "git reset"
From: Junio C Hamano @ 2005-08-24 18:35 UTC (permalink / raw)
To: Sam Ravnborg; +Cc: git, Linus Torvalds
In-Reply-To: <7vacj8nw5v.fsf@assigned-by-dhcp.cox.net>
Junio C Hamano <junkio@cox.net> writes:
> Sam Ravnborg <sam@ravnborg.org> writes:
>
>> But --soft, --hard looks rather confusing to me.
>>
>> Something like --force or --prune may be a bit more intuitive, and let
>> default behaviour be the one you name --soft for now.
>
> I do not have objections to removing --mixed, but I do not find
> --force/--prune any less confusing than --soft/--hard. Its just
> a terminology so once people get used to it anything would do.
> But I agree that we need to come up with a good name for them.
> I do not think --force/--prune is it, though.
Names aside, I have a feeling that "git reset --hard HEAD" is
what "git checkout -f HEAD" should have done. As it stands, the
latter leaves files not in HEAD but in the previous tree behind.
Comments?
^ permalink raw reply
* Re: baffled again
From: Linus Torvalds @ 2005-08-24 18:47 UTC (permalink / raw)
To: Junio C Hamano; +Cc: tony.luck, git
In-Reply-To: <7vek8jhk7y.fsf@assigned-by-dhcp.cox.net>
On Wed, 24 Aug 2005, Junio C Hamano wrote:
>
> This does not have much to do with which common ancestor
> merge-base chooses. Sorry, I am not sure what is the right way
> to resolve this offhand.
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.
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.
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.
What does this all mean? It just means that merging doesn't necessarily
even _have_ "one right answer". Automatic merges can be dangerous. The git
"global three-way" merge (global because it bases it's original state on
_global_ history, rather than local one) is about as safe as it gets (*),
but even it can have these ambigious cases that it resolves automatically,
and not the way you wanted it to.
Linus
(*) "safe as it gets" of course also means "potentially really annoying",
since it tends to require manual fixups for any even possibly half-way
ambiguous case.
^ permalink raw reply
* 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
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