On Thu, 19 Oct 2006 15:44:34 +0200, Matthieu Moy wrote: > > The lack of parents ordering in Git is directly connected with > > fast-forwarding. Yes. We're identifying the core underlying technical difference behind the recent discussion. Namely bzr treats one parent as special, (the parent that was the branch tip previously). And this special treatment eliminates the ability to fast-forward, adds merge commits that wouldn't exist with fast forwarding, and is able to make its revision numbers a bit more stable as a consequence. > > a a > > / \ / \ > > c b c b > > \ / \ / > > m m > > Yes, bzr has similar thing too. AIUI, the difference is that git does > it automatically, while bzr has two commands in its UI, "merge" and > "pull". There's a bit more to it than that though. The git command named "pull" will perform a fast-forward if possible, but will create a merge commit if necessary. For example: a a a | pulls | and fast-forwards to | b b b | | c c whereas: a a a | pulls | and creates a merge / \ b c b c \ / m So I'm curious. What does bzr pull do in the case of divergence like this? (And this is the "numbers will be changed" case, by the way). > In your case, the "leftmost ancestor" of m is b, because at the time > it was created, it was commited from b. It should be mentioned that git can, (annoyingly not by default), save a file detailing the history of a branch, (time a revision ID for every time the branch tip moved). This is the "reflog" support and provides the same information that bzr is encoding in its "leftmost ancestor" branches. Importantly, though, git's reflog is entirely local and is not propagated by push/pull etc. > One problem with that approach is that from revision m and looking > backward in history (say, running "bzr log"), you have two ways to go > backward: > > 1) Take the history of _your_ commits, and your pull till the point > where you've branched. > > 2) Follow the history taking the leftmost ancestor at each step. Uhm, don't you really have to follow both? And the only ambiguity is which one you see first? > In your scenario, repo1 would get a revision history of > "a c m" while repo2 would have had "a b m" with the same tip. OK. With git the two reflogs on the two machines would also have "a c m" and "a b m". But is this the only kind of log that exists? If I had code history as above and wanted to ask questions about what led to commit m, then I would want to know about both b and c which contribute to it. And that's what "git log" provides. It lists all the commits that are reachable from a given commit by following parent links. Surely bzr has a way to view the complete history that way? Meanwhile, I suggest that there really is no significance to which parent of a commit used to have the branch head pointing at it. Saving that information as part of the history is saving it in the wrong place. It forces the user to have to be careful about which direction merges happen, leading to awkward command sequences as demonstrated above, (or daemons to hide them). And in the end, it's just not important information to have saved in the permanent history. It is useful in a transient sense to be able to say, (as git reflog allows), what was my "master" branch pointing at yesterday, (because I know the code was working before I merged in some bad code this morning, for instance). But that's a local-only question and will never have historical significance. "What was cworth's master branch pointing at on 2006-10-18" is a question that nobody will ever need the answer to in any historical sense. -Carl PS. Here are the commands the show the divergent pull example I gave above with git: # Start a new empty repository $ mkdir git-example; cd git-example $ git init-db defaulting to local storage area # Create initial commit 'a' $ touch a; git add a; git commit -m "Initial commit of a" Committing initial tree 496d6428b9cf92981dc9495211e6e1120fb6f2ba # Create the 'b' commit on a new 'b' branch from 'a' $ git checkout -b b; touch b; git add b; git commit -m "Add b on branch b" # Create the 'c' commit on a new 'c' branch from 'a' $ git checkout -b c master; touch c; git add c; git commit -m "Add c on branch c" # Checkout the 'master' branch, (which is pointing at 'a') $ git git checkout master # Merge the 'b' branch, (notice that this is a fast forward) $ git pull . b Updating from faf5f2f7363ef5de740193afd89bedee095ef966 to 141811d050aa7008f19867280c41405e05b3dbf7 Fast forward 0 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 b # Now merge the 'c' branch (notice that this is not a fast # forward, but instead creates a new merge commit) $ git pull . c Trying really trivial in-index merge... Wonderful. In-index merge 0 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 c # Show the log of commits reachable from 'master', (all 4 commits) $ git log commit 59b3cdaf930824d4c0def4ba7ef9b913fcf05d96 Merge: 141811d... dfc35d5... Author: Carl Worth <cworth@xxxxxxxxxxxxxxx> Date: Thu Oct 19 08:15:23 2006 -0700 Merge branch 'c' commit dfc35d5bd88b22f836bd6f46991169d3c3960b69 Author: Carl Worth <cworth@xxxxxxxxxxxxxxx> Date: Thu Oct 19 08:14:30 2006 -0700 Add c on branch c commit 141811d050aa7008f19867280c41405e05b3dbf7 Author: Carl Worth <cworth@xxxxxxxxxxxxxxx> Date: Thu Oct 19 08:14:10 2006 -0700 Add b on branch b commit faf5f2f7363ef5de740193afd89bedee095ef966 Author: Carl Worth <cworth@xxxxxxxxxxxxxxx> Date: Thu Oct 19 08:13:53 2006 -0700 Initial commit of a
Attachment:
pgpOAYXsowyNJ.pgp
Description: PGP signature