git and bzr
Linus Torvalds
torvalds at osdl.org
Wed Nov 29 03:51:19 GMT 2006
On Wed, 29 Nov 2006, Joseph Wakeling wrote:
>
> So ... if I understand correctly, I can get patches from somewhere else,
> but in the branch history, I will not be able to tell the difference
> from having simply newly created them?
Think of it this way: if the _patch_ looks like it's a code movement, then
"git blame" will show it as a code movement. Ie, if the patch (to a human)
looks like it's moving a function from one file into another (which in a
patch will obviously be a question of removing it from one file, and
adding it to another), then git will also see it that way, and then "git
blame" will also follow its history as it moved.
But if somebody sends you a patch that just adds a new function that
didn't exist in that context at all, then "git blame" won't ever realize
that that new function was taken from another branch entirely.
> With regards to git blame/pickaxe/annotate, the idea of tracking *code*
> rather than files was one thing that really excited me when I read about
> it in the earlier discussion, and is probably the main reason I'm trying
> out git. I'd like to understand this properly so is there a simple
> exercise I can do to demonstrate its capabilities? I tried an
> experiment where I created one file with two lines, then cut one of the
> lines, pasted it into a new file, and committed both changes at the same
> time. But git blame -C on the second file just gives me the
> time/date/sha1 of its creation, and no indication that the line was
> taken from elsewhere.
Actually, I think you found a bug.
Now, with small changes, "git blame -C" will just ignore copies entirely,
so your particular test might not have even been supposed to work, but
trying with a new git repo with two bigger files checked in at the initial
commit, I'm actually not seeing "git blame -C" do the right thing even for
real code movement.
And the problem seems to go to the "root commit": if the file existed in
the root, the logic in "git blame" to diff against the (nonexistent)
parent of the root commit won't do the right thing, and that just confuses
git blame entirely.
I think Junio screwed up at some point. I'll send him a bug-report once
I've triaged this a bit more, but I can recreate your breakage if I start
a new git database and create two files in the root, and move data between
them in the second commit (but if I instead create the second file in the
second commit, and do the movement in the third commit, git blame -C works
again ;).
> Back to the more basic queries ... one more difference I've observed
> from bzr, after playing around for a while, involves the commands to
> undo changes and commits. It looks like git reset combines the
> capabilities of both bzr uncommit and bzr revert: I can undo changes
> since the last commit by resetting to HEAD, and I can undo commits by
> resetting to HEAD^ or earlier.
I'm not quite sure what "bzr revert" does. Git does have a "revert" too,
but it will append a _new_ commit that actually undoes the commit you're
asking to revert. If you want to just "undo history" (whether it's one
commit or many - I don't see why it would be different) then yes, "git
reset" is the thing to use.
I _suspect_ that bzr people use "uncommit" to undo a commit in order to
fix it up. In git, you could do that with "git reset" and a new commit,
but the normal thing to do is just to fix it up, and then do
git commit --amend
instead (which amends the last commit to include whatever fixups you did).
> Some things here I'm not quite sure about:
> (1) the difference between git reset --soft and git reset --mixed,
> probably because I don't understand the way the index works, the
> difference between changed, updated and committed.
You'd generally not want to use "--soft" unless you know what the index
really is. Once you do know about all the index issues, you'll know why
it's different from "--mixed", but in general, no normal person would ever
use _either_ --soft (because not changing the index is too confusing if
you don't know about it) or --mixed (because it's the default).
So in reality, you should use
git reset
to reset everything but the actual working tree (and it will talk about
the files that no longer match the state you are resetting _to_, if any
such files exist), or
git reset --hard
to reset everything.
Any other usage is strictly for hardcore people only, and if you don't
know you want to use it, you shouldn't even consider it.
In fact, I'm pretty hardcore, and I don't think I've ever really used
"--soft". It's largely been replaced by "git commit --amend", because
amending a commit used to be the only reason to use "--soft", really.
So it might even be worthwhile just dropping "--soft" and "--mixed"
altogether, but in the meantime, you might as well just ignore them.
> (2) How to remove changes made to an individual file since the last commit.
"git checkout file"
> Last, could someone explain the git merge command?
I argued that we should never teach people to use it at all (because "git
pull" really does everything it can do), but people on the git list said
people are used to merging, so it exists, and these days the syntax is
more usable than it used to be.
> git pull seems to do many things which I would need to use bzr merge
> for---I can "pull" between branches which have diverged, for example.
> I don't understand quite what git merge does that's different, and when
> to use one or the other.
Heh. I'm with you. I'm in the "don't use 'git merge' at all" camp, but it
was argued that people coming from non-git backgrounds would find it
too confusing to just use "git pull" for merging ;)
Linus
More information about the bazaar
mailing list