Re: request for documentation about branch surgery

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi,

It's been a long time since I read the user manual, so I'm only
comment to point out a few shortcuts (whether or not they're more
logical to present to new users) and clarifications on the usecases
you presented.

On Mon, Jul 6, 2009 at 5:05 PM, Bruno Haible<bruno@xxxxxxxxx> wrote:
> 1) After the section "Rewriting a single commit", it may be useful to
> have a section "Inserting one or more new commits". This is something that
> cannot be done with the "detached head" technique. I found this sequence
> of commands useful:
>
>  If you want to add a commit in the middle of a branch:
>
>            A---C---...---Z    master
>
>  =>
>
>            A---B---C---...---Z    master
>
>  it is achieved by
>
>    $ git checkout A
>    $ git branch temp
>    $ git checkout temp
>    [make changes for B]
>    $ git commit -a
>
>  now:
>
>            A---C---...---Z    master
>             \
>              --B              temp
>
>    $ git checkout master
>    $ git rebase temp
>    $ git branch -d temp

Or compress those 8 steps down to 4 using a detached HEAD and
multi-argument rebase:
  $ git checkout A
  [make changes for B]
  $ git commit -a
  $ git rebase HEAD master

The last command above means "rebase master against HEAD".  I think
the rebase command would be much easier to understand for new users if
it used an "--against" before the first reference(*).  For example,
"git rebase --against temp" for rebasing the current branch against
temp (instead of "git rebase temp") or "git rebase --against HEAD
master" (rather than "git rebase HEAD master"); the real git rebase
commands don't parse so well for new users and take a long time to
wrap ones' head around, whereas this simple change seems to make it
much easier.

(*) Except when --onto is specified.  Then --since may make more sense
than --against.  Also, I'm not yet suggesting we make this change
(since I have no patch handy), but note that if anyone wants to try
this then the "--against" should be optional for backwards
compatibility.  It's mostly a documentation change.

<snip case 2>
> 3) When do I need "git merge", and when do I need "git rebase", in the
>   context of branch surgery?
>
>   The simple answer, that I would find worth mentioning, is:
>     - "git merge" copies commits from one branch to another.

git merge does not copy commits at all; unlike cvs/svn, a commit may
(and often is) part of more than one branch in git.  A merge simply
creates a new commit which has more than one parent: the previous tip
of the current branch, and the tip of the other branch you are
merging.

>     - "git rebase" only moves commits around to make history more linear.

git rebase actually doesn't move around commits; the old commits still
exist with no modifications (which is useful for undoing rebases if
you later decide you don't like them).  Instead, git rebase just
re-applies commits, effectively making an extra "copy" of each commit
(I put "copy" in quotes because the "copied" commits will have
different parents, different commit times, and potentially different
contents especially when conflict resolution is necessary, so they're
not quite copies).

> 4) It would be good to have a section "Cutting branches"
>
>   How do I remove the N most recent commits from a branch?
>
>               D---E---F---G---H---.........---Y---Z master
>
>  =>
>               D---E master
>
>   It goes like this:
>
>     $ git checkout master
>     $ git reset --hard E

If master is the active branch, you only need the latter command.  If
master is not the active branch, then you can achieve the same with
much less cost by
  $ git branch -f master E

> 5) Then, it would be good to have a section "Replacing branches"
>
>   How do I copy the contents of a branch over to another branch, replacing
>   the recent development on that branch?
>
>  If you want to copy a branch into another, while throwing away commits:
>
>                     F1---F2---F3                         released
>                    /
>               D---E---F---G---H---.........---Y---Z master
>
>  =>
>                     F1---F2---F3   released
>                    /
>               D---E---F1---F2---F3 master
>
>  This is achieved by
>
>    $ git checkout master
>    $ git reset --hard E      # Cut the branch "master"
>    $ git merge released      # Copy commits from branch "released" to "master"

I'm assuming master isn't checked out.  If so, the following is faster:
  $ git branch -f master E

(If master is checked out, just 'git reset ---hard released')

> 6) Also, it would be good to have a section "Reconnecting branches after rebase".
>   If you want to reconnect a branch to a rebased master, here's how to do it:
>
>                   /--C'--...---P'--Q'--...---Z'  new rebased master
>              A---B---C---...---P---Q---...---Z   old master
>                                 \
>                                  --BA---...---BZ  release-branch
>
>  =>
>              A---B---C'--...---P'--Q'--...---Z'  new rebased master
>                                 \
>                                  --BA---...---BZ  release-branch
>
>  This is achieved by
>
>    $ git checkout release-branch
>    $ git rebase --onto P' P

or,
  $ git rebase --onto P' P release-branch

> This might seem exotic, but these use cases all came up while rewriting the
> history after a "git cvsimport".

They may seem exotic at first to cvs/svn refugees, but it isn't very
long before lots of users end up doing these kinds of things
routinely.

Amusing story: I spent several months at $dayjob attempting to
convince our group to switch from cvs to git instead of from cvs to
svn.  I often mentioned cool features like pulling directly from other
developers, but was often ignored and laughed off for mentioning
exotic cases that nearly no one would care about.  And our surveys
showed that most developers didn't care about anything other than
"checkout, update, and commit".  I succeeded in the end anyway, and we
found out that developers only cared about simple stuff because cvs
made anything else painful.  The very first week after switching to
git, we had multiple requests from people about how to pull changes
directly from other developers (including from people that previously
only cared about "checkout, update, and commit").

When the cost of certain activities changes dramatically (which git
does by making lots new things possible and fast), formerly "exotic"
usecases can become natural and common -- and really helpful.


Anyway, I hope some of my ramblings are useful to you.

Elijah
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux Kernel Development]     [Gcc Help]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [V4L]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Fedora Users]