git/list[1] front-page[2] threads[3] people[4] search[5] about
 

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 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
Previous: waltNext: Linus Torvalds
Message 9 of 14 in “git-bisect is magical”
  1. waltJan 9, 2006
  2. Linus TorvaldsJan 9, 2006
  3. waltJan 10, 2006
  4. Linus TorvaldsJan 10, 2006
  5. Linus TorvaldsJan 10, 2006
  6. waltJan 10, 2006
  7. Linus TorvaldsJan 10, 2006
  8. waltJan 11, 2006
  9. Junio C HamanoJan 11, 2006
  10. Linus TorvaldsJan 11, 2006
  11. waltJan 11, 2006
  12. Sytse WielingaJan 12, 2006
  13. waltJan 12, 2006
  14. Andreas EricssonJan 9, 2006

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.