I think that octopus merge (merge with more than two parents/legs) is
feature which is unique to git (isn't it?). Do you remember perhaps
why it was introduced? What does it give, beside making it difficult
to convert git repositories using this feature to others SCMs, for
example for comparison:
http://vcscompare.blogspot.com/2008/05/meet-candidates.htmlTIA
--
Jakub Narebski
Poland
--
bzr can do similar things:
bzr merge some-branch
bzr merge --force some-other-branch
bzr commitSince bzr doesn't auto-commit after a merge, the above commands
actually creates only one revision with 3 parents (the --force is here
to let merge do it's job with uncommited changes in the tree).--
Matthieu
--
But does it store octopus merge as octopus: commit with more than
two parents? In git making octopus merge is easy, perhaps too easy...True, the above actually could be inferred from mentioned blog post
http://vcscompare.blogspot.com/2008/05/meet-candidates.html
namely that there were problems with converting git repositories
containing octopus merges to Mercurial (and there was a bug in
git-fast-export which made bzr-fast-import crash on them).--
Jakub Narebski
Poland
--
Yes, it's actually a single commit object with 3 parents.
--
Matthieu
--
PRCS (http://prcs.sourceforge.net) allows to merge multiple branches
into the
current working directory, making the eventually committed version have
multiple
parents.
--
Daniel Villeneuve--
Well, mainly because the data structures supported the notion naturally.
Actually, it's trivial to convert to other SCM's, although I guess the
conversion tools haven't really tried. You can always turn it into a
series of multiple merges. Yes, you lose information, but it's not like
you lose a huge amount.As to how useful it is.. We don't have a lot of them in the kernel, but I
do have to say that the ones we have generally tend to make perfect sense.To see just octopus merges, do
git rev-list --parents HEAD |
grep '.* .* .* ' |
git diff-tree --stdin --pretty --always -S |
less -Sbut a couple of them are actually fake (same parent listed twice), due to
a confluence of (a) historically bad "git merge" semantics and (b) a bug
that made it not notice. In fact, that bug seems to have re-appeared, now
that I look at it!Junio: see kernel commits a733a5da9 and 52b097fff89, done as lately as
February of this year. We shouldn't allow that kind of thing, and in git
we have commits b389237ae and 6ea23343ce that were both about those kinds
of mis-uses.That said, most of those octopus merges look fine and actually give a
nicer view of history. Of course, Len has been known to over-do it a bit ;)Linus
--
Well, it of course depends on design. For example Mercurial (from what
I have read in the documentation) has fixed width (two element) parents
array in revflog structure. Commit can have no parents (root commit),
one parent, or two parents. There is no place (again: AFAIK) for
octopus[*1*] merge.Footnotes:
==========
[*1*] I assume that this kind of merge is called 'octopus' because it
has more than two "legs" (parents), and not for example because
first such merge had 8 parents?
--
Jakub Narebski
Poland
--
Sure. And git very much on purpose made all basic data structures be text.
I'm a UNIX weenie, not some VMS hack. Fixed-sized records are evil.
[ Yes, I made the hashes fixed-size binary blobs in the tree object. In
retrospect, that was probably a mistake. Not a huge one, but it's one of
the few things in the basic data structure that I'm sorry for. It
seemed to make sense at the time. ]I do like how you can have arbitrary parenthood (well, arbitrary on a
data structure level - we do restrict it in practice). Maybe it's not a
hugely important thing, but it does allow more than just plain merges.IOW, I could well imagine having an extra parent pointer that is not a
"data merge" pointer, but a "concept merge" - you could have branches that
have commits that point back to not the data in the tree, but to
particular commits in another branch.One of the things I could imagine using git for is to have "annotation
branches" for things like code review etc. They'd be a real branch in
their own right and with their own history, but at the same time they
could well want to point back to the "code branch" that they annotate by
considering that another parent in a "non-data merge" (and yes, you'd
obviously have to use a special merge strategy for things like that, but
you'd likely integrate it in some "annotation tool chain" rather than
anything else).Linus
--
By the way, what is status of git-notes / commit annotations? Did it got
abandoned, on hiatus, or what?--
Jakub Narebski
Poland
--
Hi,
You probably meant to Cc: me, and Linus, right?
I all but abandoned it. It works, but I do not need it, and kind of
waited for the guy who wanted them to chime in, so that I did not waste my
time in vain.IIRC it was Johan Herland, but I could be wrong.
Ciao,
Dscho--
Yes, I made the first (severely misguided) implementations [1][2] which
prompted Dscho to create an alternative implementation [3]. Although Dscho's
design was certainly more Git-esque than mine (keeping the notes in a
(pseudo)branch instead of creating a totally separate infrastructure for
note storage), at some point his efforts stalled (due to a combination of
scalability problems and/or lack of interest, IIRC).I was happy to see some of this work recently resumed by Geoffrey Irving
[4].(Side note: It is funny how Geoffrey's patch-id cache can be seen as yet
another instance of the reverse-mapping softref mechanism I proposed as
part of the first git-notes implementation [5])From the initial interest in git-notes, and the sporadic requests that have
been posted since its first mention, it seems that git-notes would be a
useful feature for many Git users. However, neither me nor Dscho have the
time/interest to keep pushing it. Maybe it's time for someone else to pick
up the torch?Have fun! :)
...Johan
[1]: http://thread.gmane.org/gmane.comp.version-control.git/46770/focus=48540
[2]: http://thread.gmane.org/gmane.comp.version-control.git/49052
[3]: http://thread.gmane.org/gmane.comp.version-control.git/52598
[4]: http://thread.gmane.org/gmane.comp.version-control.git/83484
[5]: http://thread.gmane.org/gmane.comp.version-control.git/49052/focus=49592--
Johan Herland, <johan@herland.net>
www.herland.net
--
The first one ever was actually a pentapus, 211232b (Octopus merge of the
following five patches., 2005-05-05)."gitk 211232b" was a beautiful sight back then, and it still is. The
history was much simpler back then.--
One thing to worry about is what tree object you would give to each of
these "artificially split" merge commits, though.
--
There shouldn't be, I think, a problem if octopus merge was done using
'octopus' merge strategy, which requires IIRC tree-level (trivial)
merge. But true, it is a complication, unless we fake history more,
and always use result for octopus merge as a tree.--
Jakub Narebski
Poland
--
You are sort-of right.
An octopus capable history may say "This is a merge between commit A, B
and C". A trivial/naïve conversion to a foreign history that can only
express two-parent merges must say "This X is a merge between commit A and
B", followed by "This is a merge between X and C". X, cross between A and
B, _should_ be a merge that can be reliably and trivially recreated. This
actually is the reason why "my" octopus strategy implementation refuses to
record anything nontrivial.But that's not something you should assume, as you can commit anything
with commit-tree. Some people might even be using sg/merge-options series
parked in 'pu' that makes what the recorded parenthood and what the used
parents different even more.A cleverer Octopus reimplementation might even try different orders in
which it performs its internal pairwise merges, and at that point the
order of recorded parents won't have any resemblance to the order their
trees were used in the internal pairwise merges.
--
Well, we even allow fast-forwrad to be recorded as a true merge if the
user asks these days.And the thing is, that "a733a5da9" commit has a smoking-gun evidence that
a nonsense is asked by the committer.commit a733a5da97b238e3e3167d3d0aee8fe1e8d04e97
Merge: 299cfe3... 299cfe3... 9e52797...
Author: Len Brown <len.brown@intel.com>
AuthorDate: Thu Feb 7 03:38:22 2008 -0500
Commit: Len Brown <len.brown@intel.com>
CommitDate: Thu Feb 7 03:38:22 2008 -0500Merge branches 'release' and 'fluff' into release
Conflicts:
drivers/acpi/scan.c
include/linux/acpi.hSigned-off-by: Len Brown <len.brown@intel.com>
"Merge branches 'RELEASE' and 'fluff' into RELEASE"? That happens if you
are _on_ release branch and say "git merge release fluff".Having said that, I think what is happening is that the final set of
"other parents" is computed inside git-merge out of MERGE_HEAD and that is
usually what is recorded in the resulting merge, but if the merge results
in a conflict with manual resolution, that information is not given to the
final "git commit". The resulting commit records the parents out of HEAD
and MERGE_HEAD. I do not think this part has changed from scripted
version of git-commit.
--
Right. But git shouldn't do duplicate parents. I agree it's a mis-use of
git merge, but either we should have errored out or we should have pruned
the parents.Yes, the end result is "tecnically correct", but it's not optimal.
Linus
--
On Tue, Jun 03, 2008 at 07:40:21AM -0700, Linus Torvalds <torvalds@linux-fo=
I think the current git-merge.sh already handles this: 6ea23343
introduced the usage of git-show-branch --independent to filter out
duplicated parents.
Good eyes. I guess I was sloppy when I wrote the log message for that
one and failed to talk about the bugfix ;-).--
Sorry, my thinko.
The scripted version obviously used commit-tree to omit the duplicated
parent. Perhaps we can do something like this.-- >8 --
commit: drop duplicated parentsThe scripted version of git-commit internally used git-commit-tree which
omitted duplicated parents given from the command line. This prevented a
nonsensical octopus merge from getting created even when you said "git
merge A B" while you are already on branch A.However, when git-commit was rewritten in C, this sanity check was lost.
This resurrects it.Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
builtin-commit.c | 9 +++++++++
1 files changed, 9 insertions(+), 0 deletions(-)diff --git a/builtin-commit.c b/builtin-commit.c
index b294c1f..1d8d208 100644
--- a/builtin-commit.c
+++ b/builtin-commit.c
@@ -883,10 +883,19 @@ static void add_parent(struct strbuf *sb, const unsigned char *sha1)
{
struct object *obj = parse_object(sha1);
const char *parent = sha1_to_hex(sha1);
+ const char *cp;
+
if (!obj)
die("Unable to find commit parent %s", parent);
if (obj->type != OBJ_COMMIT)
die("Parent %s isn't a proper commit", parent);
+ cp = strstr(sb->buf, parent);
+ if (cp &&
+ sb->buf + 8 <= cp && !memcmp(cp - 8, "\nparent ", 8) &&
+ cp[40] == '\n') {
+ error("duplicate parent %s ignored", parent);
+ return;
+ }
strbuf_addf(sb, "parent %s\n", parent);
}--
Junio,
have you actually tried the testcase 'Hand committing of a redundant
merge removes dups' that you included with this commit (67bfc03)? It
fails at the line 'EDITOR=: git commit -a'.Regards,
Gábor--
Yes, three times (because it is in three integration branches 'master',
'next' and 'pu') on two different machines (my primary development machine
and my k.org account before pushing the results out).Sorry, because it works for me (and presumably for many others --- I
haven't seen anybody else reporting the breakage you have), you need to
help others to diagnose it with a bit more details.
--
With debug and verbose options it says following:
* expecting success:
git rev-parse second master >expect &&
test_must_fail git merge second master &&
git checkout master g &&
echo "here comes the breakage" &&
EDITOR=: git commit -a &&
echo "survived!" &&
git cat-file commit HEAD | sed -n -e "s/^parent //p" -e "/^$/q" >actual &&
test_cmp expect actual*** Please tell me who you are.
Run
git config --global user.email "you@example.com"
git config --global user.name "Your Name"to set your account's default identity.
Omit --global to set the identity only in this repository.fatal: empty ident <szeder@neumann.(none)> not allowed
here comes the breakage
fatal: no commit message? aborting commit.
* FAIL 18: Hand committing of a redundant merge removes dupsgit rev-parse second master >expect &&
test_must_fail git merge second master &&
git checkout master g &&
echo "here comes the breakage" &&
EDITOR=: git commit -a &&
echo "survived!" &&
git cat-file commit HEAD | sed -n -e "s/^parent //p" -e "/^$/q" >actual &&
test_cmp expect actual* failed 1 among 18 test(s)
make: *** [t7502-commit.sh] Error 1My /bin/sh is dash, but it breaks with bash, too.
What else could/should I provide?
Regards,
Gábor--
Thanks, this is good enough.
I think the problem comes from the global removal of the two environment
variables, GIT_COMMITTER_{EMAIL,NAME} by an ealier bb1ae3f (commit: Show
committer if automatic, 2008-05-04).Here is a potential fix.
The first hunk is the more relevant one; although the second one is also a
fix, it is independent. It is a fix to unnecessarily loosely written test
that was done in early February.t/t7502-commit.sh | 44 ++++++++++++++++++++++++--------------------
1 files changed, 24 insertions(+), 20 deletions(-)diff --git a/t/t7502-commit.sh b/t/t7502-commit.sh
index 22a13f7..7b659b9 100755
--- a/t/t7502-commit.sh
+++ b/t/t7502-commit.sh
@@ -171,13 +171,16 @@ sed '$d' < expect.tmp > expect
rm -f expect.tmp
echo "# Committer:
#" >> expect
-unset GIT_COMMITTER_EMAIL
-unset GIT_COMMITTER_NAMEtest_expect_success 'committer is automatic' '
echo >>negative &&
- git commit -e -m "sample"
+ (
+ unset GIT_COMMITTER_EMAIL
+ unset GIT_COMMITTER_NAME
+ # must fail because there is no change
+ test_must_fail git commit -e -m "sample"
+ ) &&
head -n 8 .git/COMMIT_EDITMSG | \
sed "s/^# Committer: .*/# Committer:/" >actual &&
test_cmp expect actual
@@ -193,23 +196,24 @@ chmod +x .git/FAKE_EDITORtest_expect_success 'do not fire editor in the presence of conflicts' '
- git clean
- echo f>g
- git add g
- git commit -myes
- git branch second
- echo master>g
- echo g>h
- git add g h
- git commit -mmaster
- git checkout second
- echo second>g
- git add g
- git commit -msecond
- git cherry-pick -n master
- echo "editor not started" > .git/result
- GIT_EDITOR=`pwd`/.git/FAKE_EDITOR git commit && exit 1 # should fail
- test "`cat .git/result`" = "editor not started"
+ git clean -f &&
+ echo f >g &&
+ git add g &&
+ git commit -myes &&
+ git branch second &&
+ echo master >g
+ echo g >h
+ git add g...
Yes, the first hunk fixes the problem (and the second one does not
introduce any new breakage on my system ;)However, I don't really see why the new test failed only at me...
Thanks,
Gábor--
Perhaps it is because your GECOS setting leads to this error:
fatal: empty ident <szeder@neumann.(none)> not allowed
The reason the first hunk is a fix is because that particular test tries
to see what happens when the committer identity comes from the default
places (i.e. hostname, ident and GECOS) by removing the environment
variable. For all the other tests, however, we explicitly set committer
and author identities by setting necessary environment variables so that
the tests will be repeatable for everybody. That test, however, removed
the environment variable for all the later tests, which made them
unreliable (works for some people, not work for others).--
Because you were the only person (so far) whose gecos information wasn't
sufficient for git-commit to work. In Junio's case, the test script
accidentally unset the GIT_COMMITTER_{NAME,EMAIL} variables, which
caused git-commit to fall back on the information in /etc/passwd; it
worked, but it was doing something unintended. On your system, that
information wasn't available, so git-commit just broke.-Peff
--
Hi,
Would it not be better (simpler, cleaner) to just use an object flag?
Ciao,
Dscho--
No. Can you tell which flag is safe to use in this context without
digging around too much?
--
Hi,
Was this not in builtin-commit.c? AFAIR we said that the revision
machinery must not use flags higher than 1<<12 or so, which would be left
for users.But I see that you already have the patch in 'master', so I guess you will
not change it.Ciao,
Dscho--
| Greg KH | [GIT PATCH] driver core patches against 2.6.24 |
| debian developer | Re: Dual-Licensing Linux Kernel with GPL V2 and GPL V3 |
| Adrian Bunk | Re: LSM conversion to static interface |
git: | |
| Gerrit Renker | [PATCH 26/37] dccp: Integration of dynamic feature activation - part 1 (socket set... |
| Jarek Poplawski | Re: [PATCH] pkt_sched: Destroy gen estimators under rtnl_lock(). |
| Frans Pop | svc: failed to register lockdv1 RPC service (errno 97). |
| Linus Torvalds | Re: [GIT]: Networking |
