* git-bisect is magical
@ 2006-01-09 22:41 walt
2006-01-09 23:38 ` Linus Torvalds
2006-01-09 23:39 ` Andreas Ericsson
0 siblings, 2 replies; 14+ messages in thread
From: walt @ 2006-01-09 22:41 UTC (permalink / raw)
To: git
Arthur C. Clarke's Third Law states: Any sufficiently advanced
technology is indistinguishable from magic.
You guys have done it -- I can't distinguish git-bisect from
magic. It's wonderful, and thank you!
I used it for the first time this morning to find the commit
which caused some kernel breakage. I just sent off an email
to the developer whose commit did the breakage, and it only
took me about 45 minutes. (Now all I need to do is sit back
and wait for his reply saying 'You're an idiot!')
I have one minor suggestion for howto/isolate-bugs-with-bisect.
Linus states:
git bisect good ORIG_HEAD <- mark ORIG_HEAD as good (or
whatever other known-good
thing you booted last)
Well, in my case, I new the last good kernel was *two* updates ago,
so ORIG_HEAD wasn't the right thing to use. I had to guess what
to type instead of 'ORIG_HEAD'.
Which leads to one more question: I have my kernel configured to
add the -gxxxxxxxx localversion string to the kernel name. I took
a wild guess that the xxxxxxxx was the right thing to substitute
for 'ORIG_HEAD' and I got lucky. But what about someone who
doesn't know the magic 'xxxxxxxx' to use? If I didn't know enough
to keep a week's worth of daily kernel-builds with the 'xxxxxxxx'
to guide me, would I still be able to do what I did today?
(For example, if this had been a 'git' bug instead of a kernel bug,
I don't think I could have figured out how to use git-bisect to find
the bug -- could I?)
Thanks!
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: git-bisect is magical
2006-01-09 22:41 git-bisect is magical walt
@ 2006-01-09 23:38 ` Linus Torvalds
2006-01-10 19:19 ` walt
2006-01-09 23:39 ` Andreas Ericsson
1 sibling, 1 reply; 14+ messages in thread
From: Linus Torvalds @ 2006-01-09 23:38 UTC (permalink / raw)
To: walt; +Cc: git
On Mon, 9 Jan 2006, walt wrote:
>
> Arthur C. Clarke's Third Law states: Any sufficiently advanced
> technology is indistinguishable from magic.
>
> You guys have done it -- I can't distinguish git-bisect from
> magic. It's wonderful, and thank you!
Hey, I'm pretty damn happy with it myself, if I may say so ;)
It's the _one_ feature that we really never had with BK, and that git does
really really well.
> I have one minor suggestion for howto/isolate-bugs-with-bisect.
> Linus states:
> git bisect good ORIG_HEAD <- mark ORIG_HEAD as good (or
> whatever other known-good
> thing you booted last)
>
> Well, in my case, I new the last good kernel was *two* updates ago,
> so ORIG_HEAD wasn't the right thing to use. I had to guess what
> to type instead of 'ORIG_HEAD'.
Well, instead of guessing, you can always do the safe thing, and just try,
or just going far enough back to be really safe.
The "go far back" case is obviously wasteful, and if you go _too_ far
back, you'll just spend a long time bisecting, but on the other hand,
a binary search is pretty damned efficient, so even going back _way_ too
far usually just results in a couple more bisection attempts.
But if you're unsure, before marking somethng "good", you can just test it
out first, by doing something like
git checkout -b test <version-to-test-here>
and compiling and testing that one. If it's good, you can just do a simple
"git bisect good" to say that the current state was good..
Oh, and in general you don't ever have to name the good/bad ones: the
example in Documentation/howto states that you should say
git bisect bad master
git bisect good ORIG_HEAD
but the fact is, whenever you leave off the version specifier, it will
just assume that "current HEAD" is it. So quite often, a "git bisect" run
will start with just a simple
git bisect bad
to mark that the current head is bad (of course, that's 100% equivalent to
saying "git bisect bad master" if you are on the master branch right
then).
And if you don't remember what your last good kernel was, but you're sure
that the last full release was good, you can just do
git bisect good v2.6.15
and be done with it.
(Of course, right now there's 2075 commits in my git tree after 2.6.15, so
that's a fair amount of bisecting.. But let's say that you had known more
exactly, and been able to start off with just 300 commits - you only have
to do three "bisect" runs to whittle the 2075 commits down to that range
anyway - so it's not like you are totally screwed even if you don't know
where the good one was).
> Which leads to one more question: I have my kernel configured to
> add the -gxxxxxxxx localversion string to the kernel name.
Good man.
> I took
> a wild guess that the xxxxxxxx was the right thing to substitute
> for 'ORIG_HEAD' and I got lucky.
Yes. I guess we should document what the "-gxxxxx" thing means in the
kernel, and that it's simply the short-hand git name for the top commit
when the kernel was compiled. So you did exactly the right thing.
> But what about someone who
> doesn't know the magic 'xxxxxxxx' to use? If I didn't know enough
> to keep a week's worth of daily kernel-builds with the 'xxxxxxxx'
> to guide me, would I still be able to do what I did today?
Yes. See above. It certainly takes you more effort, but it's not _hugely_
more effort.
> (For example, if this had been a 'git' bug instead of a kernel bug,
> I don't think I could have figured out how to use git-bisect to find
> the bug -- could I?)
Well, if you know how git works internally, it's actually fairly easy to
do with any random project. You could, for example, just test whether
git-1.0.6 was good first. Or, again, just use a sledge-hammer, and go for
the original 1.0.
The alternative is to just ignore tagged versions altogether, and go by
date. For example, you could do something like
git log --since=1.week.ago
and just go to the end (right now, for me, that would be commit 8b32572,
aka "git-init-db(1): Describe --shared and .."). Again, just do
git checkout -b test 8b32572
and try that. If it was good, just mark it good and go from there. The
test cycle for git is going to be a lot faster than the test cycle for the
kernel, so you'll find any bug in no time.
Linus
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: git-bisect is magical
2006-01-09 22:41 git-bisect is magical walt
2006-01-09 23:38 ` Linus Torvalds
@ 2006-01-09 23:39 ` Andreas Ericsson
1 sibling, 0 replies; 14+ messages in thread
From: Andreas Ericsson @ 2006-01-09 23:39 UTC (permalink / raw)
To: walt; +Cc: git
walt wrote:
>
> I have one minor suggestion for howto/isolate-bugs-with-bisect.
> Linus states:
> git bisect good ORIG_HEAD <- mark ORIG_HEAD as good (or
> whatever other known-good
> thing you booted last)
>
> Well, in my case, I new the last good kernel was *two* updates ago,
> so ORIG_HEAD wasn't the right thing to use. I had to guess what
> to type instead of 'ORIG_HEAD'.
>
It would be neat if resets could optionally be stored as unannotated
tags as well as ORIG_HEAD, with a date and time in the tag-name.
git tag reset-$(date '+%F_%H.%M.%S')
works fine for me, although I expect the quibbling about the date-format
will never stop. I'll get going on it tomorrow unless I get some
seriously vehement requests not to, or someone beats me to it.
If someone *does* beat me to it, perhaps "git reset --clean-tags" should
be implemented as well?
> Which leads to one more question: I have my kernel configured to
> add the -gxxxxxxxx localversion string to the kernel name. I took
> a wild guess that the xxxxxxxx was the right thing to substitute
> for 'ORIG_HEAD' and I got lucky. But what about someone who
> doesn't know the magic 'xxxxxxxx' to use?
I expect you remember the date and approximate time you built it so the
--tag option should work fairly well there, I'd say. Otherwise, tagging
the build like you do is a very good idea.
>If I didn't know enough
> to keep a week's worth of daily kernel-builds with the 'xxxxxxxx'
> to guide me, would I still be able to do what I did today?
> (For example, if this had been a 'git' bug instead of a kernel bug,
> I don't think I could have figured out how to use git-bisect to find
> the bug -- could I?)
>
Most likely not as easily, although it would have been fairly easy to
mark the most recent tag as a known good build, or Linus' latest tree
from upstream.
--
Andreas Ericsson andreas.ericsson@op5.se
OP5 AB www.op5.se
Tel: +46 8-230225 Fax: +46 8-230231
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: git-bisect is magical
2006-01-09 23:38 ` Linus Torvalds
@ 2006-01-10 19:19 ` walt
2006-01-10 19:42 ` Linus Torvalds
0 siblings, 1 reply; 14+ messages in thread
From: walt @ 2006-01-10 19:19 UTC (permalink / raw)
To: git
Linus Torvalds wrote:
[...]
> but the fact is, whenever you leave off the version specifier, it will
> just assume that "current HEAD" is it...
I'm still very much struggling with nomenclature, and trying to
deduce what is a synonym for what, and which words cannot be used
synonymously.
Yesterday (while reading the bisect HOWTO) I did a git-revert on the
'bad' commit, which indeed fixed my bug. But this caused a problem
this morning when I did my daily 'cg-update' for the kernel.
I got a merge conflict (of course) because of yesterday's git-revert.
My question (I think) is: exactly what did I change when I did the
git-revert? I notice in retrospect that (in refs/heads) master is
no longer identical to origin. I think (but I'm not certain) that
the two used to be the same. (For example, in my 'git' repository
the 'master' and 'origin' files are identical.)
Did the git-revert change my local kernel repository permanently?
Did the merge-conflict prevent today's cg-update from updating my
local repository with your commits from the last 24 hours? Or is
the merge conflict only with my currently checked-out-and-modified
copy of the repository?
Is it clear to you why I'm confused? :o) Most of my muddle is
because I don't know the definitions of some important words, I
suspect.
Thanks!
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: git-bisect is magical
2006-01-10 19:19 ` walt
@ 2006-01-10 19:42 ` Linus Torvalds
2006-01-10 19:45 ` Linus Torvalds
0 siblings, 1 reply; 14+ messages in thread
From: Linus Torvalds @ 2006-01-10 19:42 UTC (permalink / raw)
To: walt; +Cc: git
On Tue, 10 Jan 2006, walt wrote:
>
> Yesterday (while reading the bisect HOWTO) I did a git-revert on the
> 'bad' commit, which indeed fixed my bug. But this caused a problem
> this morning when I did my daily 'cg-update' for the kernel.
>
> I got a merge conflict (of course) because of yesterday's git-revert.
Well, it's not "of course". It might have merged fine, and to some degree
you were just unlukcy that it created a conflict with new development),
but yes, it will now always be a _merge_ rather than a fast-forward, as
your tree was now different from my historical tree.
> My question (I think) is: exactly what did I change when I did the
> git-revert?
You can think of a "git revert" as being just a "apply the reverse of that
one diff, and commit it". So a "git revert" really just add a _new_
commit, it never _removes_ anything.
(That's fundamental: in a distributed system you can't undo history).
Now, strictly speaking "git revert" actually does something much smarter
than just apply the diff in reverse - which means that it works better if
other things have changed in that area - but if you think of it as the
"commit the diff in reverse" case, you'll be thinking the right way.
> I notice in retrospect that (in refs/heads) master is
> no longer identical to origin. I think (but I'm not certain) that
> the two used to be the same. (For example, in my 'git' repository
> the 'master' and 'origin' files are identical.)
Exactly.
Do a "git-whatchanged -p", and you'll see what your "git revert" did.
> Did the git-revert change my local kernel repository permanently?
Yes.
You can _undo_ the revert, so it's not permanent in that sense. Just do
git reset --hard origin
and your "master" branch will be forced back to the state that "origin"
was in.
> Did the merge-conflict prevent today's cg-update from updating my
> local repository with your commits from the last 24 hours? Or is
> the merge conflict only with my currently checked-out-and-modified
> copy of the repository?
I'm not sure. It could be either, you don't tell what the conflict message
is.
If the conflict message is
Entry 'xyzzy' not uptodate. Cannot merge.
that means that no merge was even tried, because you had dirty contents in
your tree, and the merge simply won't touch it. You need to commit the
dirty state and let the merge try to auto-merge it, or you need to undo
it so that your tree is clean.
If the conflict message is something like
CONFLICT (content): merge conflict in xyzzy
that means that the merge _was_ done, but there was a content conflict
that you need to fix up by hand and finish the merge.
> Is it clear to you why I'm confused? :o) Most of my muddle is
> because I don't know the definitions of some important words, I
> suspect.
Hey, keep the questions coming. And if something starts making sense, I
suspect that Junio would be very happy with additions to the Documentation
subdirectory to try to help others... Hint, hint.
Linus
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: git-bisect is magical
2006-01-10 19:42 ` Linus Torvalds
@ 2006-01-10 19:45 ` Linus Torvalds
2006-01-10 20:43 ` walt
0 siblings, 1 reply; 14+ messages in thread
From: Linus Torvalds @ 2006-01-10 19:45 UTC (permalink / raw)
To: walt; +Cc: git
On Tue, 10 Jan 2006, Linus Torvalds wrote:
>
> You can _undo_ the revert, so it's not permanent in that sense. Just do
>
> git reset --hard origin
>
> and your "master" branch will be forced back to the state that "origin"
> was in.
Btw, you can try this (careful - it will also undo any dirty state you
have in your working tree), and then do the "pull" again (which should now
be a trivial fast-forward) and then just try to do the "git revert" on the
new state.
An even better option is obviously to figure out _why_ that commit broke
for you in the first place, and get it fixed up-stream, so that you don't
even need to revert it any more, and the "pull" just fixes it for you ;)
Linus
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: git-bisect is magical
2006-01-10 19:45 ` Linus Torvalds
@ 2006-01-10 20:43 ` walt
2006-01-10 21:17 ` Linus Torvalds
0 siblings, 1 reply; 14+ messages in thread
From: walt @ 2006-01-10 20:43 UTC (permalink / raw)
To: git
Linus Torvalds wrote:
>
> On Tue, 10 Jan 2006, Linus Torvalds wrote:
>> You can _undo_ the revert, so it's not permanent in that sense. Just do
>>
>> git reset --hard origin
>>
>> and your "master" branch will be forced back to the state that "origin"
>> was in.
>
> Btw, you can try this (careful - it will also undo any dirty state you
> have in your working tree), and then do the "pull" again (which should now
> be a trivial fast-forward) and then just try to do the "git revert" on the
> new state.
Just by stumbling around and trying things at random, I did a
'git-checkout origin' which *seemed* to resolve the merge-conflict,
but left me feeling uneasy because I don't really understand what
I'm doing. Can you give a short explanation of the difference
between 'git reset --hard origin' and 'git-checkout origin'?
> An even better option is obviously to figure out _why_ that commit broke
> for you in the first place, and get it fixed up-stream...
I'm still waiting for the insulting email from the developer ;o) How
long should I wait for a response before I start bugging other people?
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: git-bisect is magical
2006-01-10 20:43 ` walt
@ 2006-01-10 21:17 ` Linus Torvalds
2006-01-11 1:50 ` walt
0 siblings, 1 reply; 14+ messages in thread
From: Linus Torvalds @ 2006-01-10 21:17 UTC (permalink / raw)
To: walt; +Cc: git
On Tue, 10 Jan 2006, walt wrote:
>
> Just by stumbling around and trying things at random, I did a
> 'git-checkout origin' which *seemed* to resolve the merge-conflict,
> but left me feeling uneasy because I don't really understand what
> I'm doing. Can you give a short explanation of the difference
> between 'git reset --hard origin' and 'git-checkout origin'?
"git checkout" actually checks out a different branch (unless, to confuse
things, you ask it to just check out a specific _file_, in which case it
stays on the same branch).
So when you say "git checkout origin", it actually _switches_ to the
origin branch (which is just my state) and checks that out.
When you then do a "git pull", you'll just be pulling my newer state into
that older content branch, and it will resolve beautifully as a
fast-forward with no merge at all.
The downside with being in the "origin" branch is that if you now do any
kind of real development, you've now made "origin" mean something else
than it traditionally means - now it's no longer a branch tracking the
origin of your code, now it's an active development branch.
Do "git checkout master" to go back to where you used to be.
In contrast, a "git reset --hard origin" would have reset your _current_
branch to the state that the "origin" branch was in (and forced a checkout
of that exact state too - that's what the "--hard" flag means).
So when you say "git checkout origin", you should read it as "check out
the origin branch", and thus it makes perfect sense that "origin" now
becomes your current branch. In contrast, when you say "git reset --hard
origin", you should mentally read that as "reset the state of my current
tree to the same state as the origin branch".
The naming does make sense, but you just have to get used to what
"checkout" means (in its two different guises - checking out a file being
different from checking out a full tree) and what "reset" means.
> > An even better option is obviously to figure out _why_ that commit broke
> > for you in the first place, and get it fixed up-stream...
>
> I'm still waiting for the insulting email from the developer ;o) How
> long should I wait for a response before I start bugging other people?
Hey, send out the report to linux-kernel, and if it is a serious problem,
just cc me and Andrew (and whoever else seems to be most relevant for the
area: networking goes to David Miller, drivers mostly to Greg or Jeff etc
etc). Regardless, you should always cc at least the people who signed off
on the commit, since they want to know that they signed off on something
that turned out to be buggy.
Linus
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: git-bisect is magical
2006-01-10 21:17 ` Linus Torvalds
@ 2006-01-11 1:50 ` walt
2006-01-11 2:47 ` Junio C Hamano
2006-01-11 2:58 ` Linus Torvalds
0 siblings, 2 replies; 14+ messages in thread
From: walt @ 2006-01-11 1:50 UTC (permalink / raw)
To: git
Linus Torvalds wrote:
[...]
> So when you say "git checkout origin", it actually _switches_ to the
> origin branch (which is just my state) and checks that out.
I think we are finally homing in on the very roots of my ignorance!
When you use the word 'switches' my eyes go glassy, just like when
my wife starts telling me everything I've done wrong today...
Please --> what am I switching *from* when I switch to 'origin'?
(Think: this guy is a total dumbshit! How can I possibly dumb-
down this basic knowledge any dumber?)
I know this is really bone-head-basic-stuff, but I'm quite sure
that this lies at the heart of my confusion.
When I finally understand this kindergarten material I can graduate
to first grade :o)
Thanks for your patience!
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: git-bisect is magical
2006-01-11 1:50 ` walt
@ 2006-01-11 2:47 ` Junio C Hamano
2006-01-11 2:58 ` Linus Torvalds
1 sibling, 0 replies; 14+ messages in thread
From: Junio C Hamano @ 2006-01-11 2:47 UTC (permalink / raw)
To: walt; +Cc: git
walt <wa1ter@myrealbox.com> writes:
> Linus Torvalds wrote:
> [...]
>> So when you say "git checkout origin", it actually _switches_ to the
>> origin branch (which is just my state) and checks that out.
>
> Please --> what am I switching *from* when I switch to 'origin'?
Short version: if you have only two branches "master" and
"origin", then obviously there is only one "the other one" ;-).
Longer version:
At the very beginning, you started your repository like this:
$ git clone git://git.kernel.org/some/where mine
$ cd mine
You can say:
$ git branch
And you would see:
$ git branch
* master
origin
So you have two branches, and you are on "master" right now.
Your working tree files are associated with one branch at any
moment, and "git branch" shows you which branch you are on.
That branch is "the current branch". When you make your
commits, you will commit into that branch. The commit-producing
commands include "git commit", "git am", "git pull", "git
merge", "git revert" and "git cherry-pick". They all create a
new commit on your "current branch". The difference among them
is where the commit you create takes the modifications from
(commit from the index file and the working tree, am from a
mailbox, pull and merge from a different branch, and revert and
cherry-pick from an existing commit).
You usually work in your "master" branch. But you do not have
to. Suppose you are working on maintaining some product, and
you have a couple of trivial bugfixes you can make and one
rather involved enhancement. What you could do is to have more
than one branches, and use "master" for what are ready to be
consumed by other people, and another branch for your
developments.
Your repository at one point might look like this:
$ git show-branch
* [master] trivial fix #2
! [devel] work in progress #3
--
+ [devel] work in progress #3
+ [devel^] work in progress #2
+ [devel~2] work in progress #1
+ [master] trivial fix #2
+ [master^] trivial fix #1
++ [master~2] released frotz gadget
You are on the "master" branch, and committed two trivial fixes
on top of it since your last release. But in the meantime you
found time to do independent enhancements, not yet finished but
slowly progressing. You hope to be able to complete the
development and include that in the master branch eventually,
but not yet.
How you would end up to something like above would go like this:
1. You have just released frotz gadget. Your "master" branch
is at that commit, and you do not have the "devel" branch
yet.
2. You are inspired by somebody to enhance frotz in a novel
way. You start hacking and accumulate some changes in the
working tree files, but now you realize it will be a bigger
task than you initially thought. In the meantime, you got a
couple of bug reports and you think you know how to fix them
trivially. But unfortunately, your working tree files are
currently in a great mess. Then:
$ git checkout -b devel
This creates a new branch ("devel") based on the current
branch head (remember, you were on "master" branch), and
switches to that new branch. It is a short-hand for the two
command sequence:
$ git branch devel
$ git checkout devel
This takes your working tree changes with you, so at this
point if you do "git diff", you will see your changes. You
commit this mess (do not worry about "presentable history"
yet; you will be cleaning up the mess later anyway before
you merge).
$ git add new-files-you-created
$ git commit -a -m 'work in progress #1'
3. Now you can switch mood and can work on the trivial fixes.
Go back to the "master" branch:
$ git checkout master
you'll notice that all the mess you made while working on
devel has been cleaned up --- WIP edits are gone, and if you
made new files for "devel" they are gone too. You start
from the state immediately after release, and work on fixes,
and commit:
$ edit for trivial fix number 1
$ git commit -a -m 'trivial fix #1'
$ edit for trivial fix number 2
$ git commit -a -m 'trivial fix #2'
4. Now fixes are out of your way, you can go back to work on
the enhancements. The same thing as step 3.
$ git checkout devel
$ edit / test / commit
Eventually what you do in your devel branch comes to maturity
and ready for public consumption. How would you make sure when?
For that, you would create a throw-away test branch and try
things out:
$ git branch -f test master
$ git checkout test
$ git merge 'development trial' test devel
This would create something like this:
$ git show-branch
! [master] trivial fix #2
! [devel] work in progress #3
* [test] development trial
---
+ [test] development trial
++ [devel] work in progress #3
++ [devel^] work in progress #2
++ [devel~2] work in progress #1
+ + [master] trivial fix #2
+ + [master^] trivial fix #1
+++ [master~2] released frotz gadget
You merged "devel" and "master" in "test" branch, so that you
can test your development along with the other fixes you had in
the "master" branch since your "devel" branch forked. Try
things out and if you find the result satisfactory, then you
know what you have in "devel" is good for public consumption.
There are three ways to bring the "devel" into "master" at this
moment. It depends on how much you care about clean history.
A) just merge.
$ git checkout master
$ git pull . devel
This is the simplest, but you would see all the real history
in "devel" branch, things like "work in progress #n" commit
log messages.
B) refactor and linearize.
$ git format-patch -k -m -o ./+redo master..devel
This leaves a patchfile per commit in devel branch in +redo/
directory. You can edit the commit log message and patch
just as if you are preparing them for e-mail submission to
another project maintainer. Once you are done editing:
$ git checkout master
$ git am -k -3 ./+redo/0*.txt
to apply them on top of the master branch.
C) linearize without refactoring.
$ git checkout devel
$ git rebase master
$ git checkout master
$ git pull . devel
This "rebases" the development branch (the first two steps),
and then pulls the result into the "master" branch (the
rest). It should give you the same result as approach B) if
you do not edit your +redo/ files at all.
Once you are done, you can clean up by
$ git branch -D test devel
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: git-bisect is magical
2006-01-11 1:50 ` walt
2006-01-11 2:47 ` Junio C Hamano
@ 2006-01-11 2:58 ` Linus Torvalds
2006-01-11 18:07 ` walt
1 sibling, 1 reply; 14+ messages in thread
From: Linus Torvalds @ 2006-01-11 2:58 UTC (permalink / raw)
To: walt; +Cc: git
On Tue, 10 Jan 2006, walt wrote:
>
> Linus Torvalds wrote:
> [...]
> > So when you say "git checkout origin", it actually _switches_ to the
> > origin branch (which is just my state) and checks that out.
>
> I think we are finally homing in on the very roots of my ignorance!
>
> When you use the word 'switches' my eyes go glassy, just like when
> my wife starts telling me everything I've done wrong today...
Ahhah.
> Please --> what am I switching *from* when I switch to 'origin'?
> (Think: this guy is a total dumbshit! How can I possibly dumb-
> down this basic knowledge any dumber?)
Ok, this clearly isn't described well enough in any docs, so let me try,
and hopefully somebody (hint hint) will go "Ahh, I wish that had been
described in xyz - here's a patch to do so".
Anyway, the notion of multiple "branches" aka "heads of development" is
pretty ingrained in git. It's really how _everything_ subtle gets done
(merging, you name it - sometimes the branch may be a temporary unnamed
head that is just inside a script, but the _concept_ is always there).
There's one _special_ branch, which is the "active" one. The only git
trees without an active branch are the so-called "bare" git trees, which
are the .git directory contents directly, without any checked-out state.
Those are only used for distribution - no development can ever happen in
them, because they simply don't have any active branch to do development
_in_.
But for any normal git repository, you'll have one active branch, which is
the one that your working directory actually represents. It's also the one
we call "HEAD", since the HEAD thing is the thing that points to the
active branch.
Your HEAD can point to _any_ branch, but the default one is called
"master". That's the branch you get when you clone another repository, or
when you just start a new git repository from scratch with "git-init-db".
But you can "switch" between branches at any time by just doing a simple
"git checkout <branchname>". That will conceptually totally blow away your
working directory contents (well, all of it that git knows about, anyway),
and replace them with the contents that the _other_ branch contains. Now,
I say "conceptually", because in practice this is heavily optimized, so
that any files that don't change aren't actually re-written, so you can
switch between two branches that are similar quite cheaply.
So when you did "git checkout origin", you basically blew away all the
development you had done in the default "master" branch, and switched to
_another_ branch. The "origin" branch is the one that is generated for you
automatically when you clone a repository from somewhere else: it
initially contains the state of that other repository at the time of the
clone, and a "git pull origin" will actually both "fetch" that branch (so
that the "origin" branch is kept up-to-date with the original source)
_and_ merge that branch into your HEAD (normally "master").
> I know this is really bone-head-basic-stuff, but I'm quite sure
> that this lies at the heart of my confusion.
>
> When I finally understand this kindergarten material I can graduate
> to first grade :o)
Well, at least _some_ of this is described in Documentation/git-pull.txt
and Documentation/tutorial.txt. So if you haven't looked into those
before, try them now. And if you have, they clearly need more effort.
I'm really bad at documentation. I'm more than happy trying to answer
emailed questions (at least if I get the feeling that the person asking
the questions is really trying to learn, which you've done admirably), but
that doesn't mean that I'm good at writing the docs. So I'm hoping that
some of this can find itself into a FAQ or one of the existing docs,
thanks to somebody else editing it..
Linus
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: git-bisect is magical
2006-01-11 2:58 ` Linus Torvalds
@ 2006-01-11 18:07 ` walt
2006-01-12 21:59 ` Sytse Wielinga
0 siblings, 1 reply; 14+ messages in thread
From: walt @ 2006-01-11 18:07 UTC (permalink / raw)
To: git
Linus Torvalds wrote:
[...]
> So when you did "git checkout origin", you basically blew away all the
> development you had done in the default "master" branch, and switched to
> _another_ branch...
First, many thanks to you, Junio, and Sean (by email) for the great
replies -- all three were extremely helpful, and this is all finally
starting to make sense to me.
Now, I don't know whether this anecdote will give you any new
information, but I'll offer it.
After I did the 'git checkout origin' yesterday, I didn't (yet) know
what I was doing, so I made the following pilot-errors while still
in 'origin': I did 'git-reset --hard origin' and then very early
this morning I did cg-update, both of which seemed to work fine and
gave no error messages, and I compiled a new kernel from the result.
After reading the three essays from you guys :o) I realized that I
had made these two mistakes, and tried to switch back to master:
$git-branch
bisect
master
* origin
$git-checkout master
fatal: Entry 'Documentation/kernel-parameters.txt' would be overwritten
by merge. Cannot merge.
So I cloned a fresh copy of your repository and built a new kernel.
What I learned from this was that the new fixes to Makefile and
setlocalversion (at a minimum) were not actually applied to the
checked-out sources in my 'origin' misadventure. (I watched the
commits being listed by cg-update, so I know the fixes were really
downloaded -- but they were not applied to the checked-out sources
as they normally would be.)
Would these anomalous results be expected -- given the, um, unusual
circumstances?
Thanks again!
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: git-bisect is magical
2006-01-11 18:07 ` walt
@ 2006-01-12 21:59 ` Sytse Wielinga
2006-01-12 23:49 ` walt
0 siblings, 1 reply; 14+ messages in thread
From: Sytse Wielinga @ 2006-01-12 21:59 UTC (permalink / raw)
To: walt; +Cc: git
On Wed, Jan 11, 2006 at 10:07:19AM -0800, walt wrote:
> [...]
> After I did the 'git checkout origin' yesterday, I didn't (yet) know
> what I was doing, so I made the following pilot-errors while still
> in 'origin': I did 'git-reset --hard origin' and then very early
> this morning I did cg-update, both of which seemed to work fine and
> gave no error messages, and I compiled a new kernel from the result.
>
> After reading the three essays from you guys :o) I realized that I
> had made these two mistakes, and tried to switch back to master:
> $git-branch
> bisect
> master
> * origin
> $git-checkout master
> fatal: Entry 'Documentation/kernel-parameters.txt' would be overwritten
> by merge. Cannot merge.
>
> So I cloned a fresh copy of your repository and built a new kernel.
Funny thing about git is, at least in my experience, that you generally never
really have to do this. Because objects are immutable, and basically the only
thing git -really- cares about is objects, you can always tell git to just
ignore anything you've done (or that anybody else has done, for that matter).
Just point it to an object somebody else made and it won't see any of your
local changes. If you're not satisfied with the way a branch worked out, just
remove it, or point it to another object.
By the way, you can always just move away a broken origin; git-fetch (or
git-pull of course, because it uses git-fetch), will just create a new one. If
git-branch shows that you currently have origin checked out, do
# Create a new branch named 'bad-bad-origin' based on HEAD (which equals
# origin at the moment) and check it out
git-checkout -b bad-bad-origin
otherwise do (because it is faster, as it doesn't touch your index file or
your working tree)
# Create a new branch named 'bad-bad-origin' based on origin
git-branch bad-bad-origin origin
... and finally remove the old origin:
git-branch -d origin
After this, a git-fetch will just recreate origin, and unlike git-pull does
nothing that could give you more headbreaks again, so that fixes your broken
origin. Then optionally backup your master by saying
git-branch old-master master
and get yourself a nice and clean repository again by typing:
git-checkout master
# Reset the current HEAD (namely, master) to origin
git-reset --hard origin
Before executing any git command that will check out a different tree, though,
you will want to make sure you know what you have done to your working tree and
what git will do to your edits when you execute that command. git-diff*,
git-ls-files, and git-status are your friends. If either git-ls-files -m or
git-ls-files -u (or the combination git-ls-files -m -u, naturally) shows any
files, git will refuse to switch branches if it has to touch any of these
files.
If you're sure you don't want these changes anymore, you can undo any changes
with 'git-reset --hard'. If you wish to save these changes however, you can
either take the classic approach of saving a diff with git-diff HEAD (just a
plain git-diff won't do for files in git-ls-files -u, that is, files that you
already ran git-update-index on) or you can make a commit and save it in a
temporary branch.
For example, you can make a commit before or after the 'git-checkout -b
bad-bad-origin' in the beginning of this mail, and the diff will be in
bad-bad-origin for your later reference by using git-diff-tree -p
bad-bad-origin.
By the way, if you really don't know what to do anymore, there always is the
last resort of fixing things up manually. I'm not recommending you to go this
way, but it has helped me out a couple of times before I knew all the basic
commands, so it seems good to at least mention how you do it.
All branches are in .git/refs/heads/, so you can just go there and move master
and origin or any other branch that you like to another name, or remove them,
or overwrite them with references you pick from other files in .git/refs/heads/
or git log. Just make sure all they contain is a full sha1-hash, so no names,
just the hash. And that .git/HEAD is a symlink pointing to one of the files in
refs/heads/.
The drawback, and the reason you should generally not do this unless you don't
know any better way to do what you want, is that you can leave the index file
and the working tree in a state that doesn't correspond to the current HEAD
anymore. To be sure, you can always go back to the top directory and do a
'git-reset --hard', and then a 'git-ls-files -z -o |xargs -0 rm --'. This will
remove any extra files that you have in your working tree, mind you, so make
sure you move those you still need out of the working tree before doing this.
> What I learned from this was that the new fixes to Makefile and
> setlocalversion (at a minimum) were not actually applied to the
> checked-out sources in my 'origin' misadventure. (I watched the
> commits being listed by cg-update, so I know the fixes were really
> downloaded -- but they were not applied to the checked-out sources
> as they normally would be.)
>
> Would these anomalous results be expected -- given the, um, unusual
> circumstances?
Yes. If git tries a merge, but fails, it will leave the results in the working
tree for you to fix, so that you can finish the merge. If you don't wish to
finish the merge, just do a git-reset --hard and your tree is clean again.
> Thanks again!
No thank _you_, for explaining so well what exactly you didn't understand! :-)
Sytse Wielinga
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: git-bisect is magical
2006-01-12 21:59 ` Sytse Wielinga
@ 2006-01-12 23:49 ` walt
0 siblings, 0 replies; 14+ messages in thread
From: walt @ 2006-01-12 23:49 UTC (permalink / raw)
To: git
Sytse Wielinga wrote:
[...]
> No thank _you_, for explaining so well what exactly you didn't understand! :-)
I am totally blown away by the amount of useful information in your
post! I have scanned through what you sent, but I will need some time
to digest it all.
I promise you that I *will* understand every word of what you wrote,
even if I have to ignore my wife for a week! (Maybe longer ;o)
Thank you! I foresee a great future for you in private industry.
(I say that because the ability to write clearly is not very much
valued in government or academia...)
^ permalink raw reply [flat|nested] 14+ messages in thread
end of thread, other threads:[~2006-01-12 23:49 UTC | newest]
Thread overview: 14+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2006-01-09 22:41 git-bisect is magical walt
2006-01-09 23:38 ` Linus Torvalds
2006-01-10 19:19 ` walt
2006-01-10 19:42 ` Linus Torvalds
2006-01-10 19:45 ` Linus Torvalds
2006-01-10 20:43 ` walt
2006-01-10 21:17 ` Linus Torvalds
2006-01-11 1:50 ` walt
2006-01-11 2:47 ` Junio C Hamano
2006-01-11 2:58 ` Linus Torvalds
2006-01-11 18:07 ` walt
2006-01-12 21:59 ` Sytse Wielinga
2006-01-12 23:49 ` walt
2006-01-09 23:39 ` Andreas Ericsson
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).