Re: git-bisect is magical
- From
Junio C Hamano <junkio@cox.net>
- Date
- Jan 11, 2006, 02:47 UTC
- Message-ID
- <7vhd8b1nw7.fsf@assigned-by-dhcp.cox.net>
- In-Reply-To
- <dq1o88$1bm$1@sea.gmane.org>
walt <wa1ter@myrealbox.com> writes:
Show 6 quoted lines
> 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 mineYou can say:
$ git branch
And you would see:
$ git branch
* master
originSo 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 gadgetYou 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 develThis 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 gadgetYou 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*.txtto 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