[Nfd-dev] git rebase question

Alex Afanasyev aa at CS.UCLA.EDU
Tue Sep 8 23:20:35 PDT 2015


> On Sep 8, 2015, at 8:51 PM, Wentao Shang <wentaoshang at gmail.com> wrote:
> 
>> 
>> On Sep 8, 2015, at 7:41 PM, Junxiao Shi <shijunxiao at email.arizona.edu> wrote:
>> 
>> Dear folks
>> 
>> Recently, Alex has been suggesting that commits in a feature branch (such as NFD management refactor, NDNLP implementation, etc) should not be merged until all commits are ready, and developers may start working on an unmerged parent commit.
>> This would require the developer to rebase their commits, if the parent commit changes.
>> I’m reluctant to do that, but prefers to wait for the parent commit to be merged before starting the next commit, because I had a lot of trouble in rebasing.
>> 
>> Specifically, my trouble starts with this situation:
>> 	• commit1 is already merged.
>> 	• commit2a is an unmerged commit on Gerrit, which is based on commit1.
>> 	• commit3 is the commit that I’m working on, which is based on commit2a.
>> 	• Now commit2a is modified, and the new patchset is commit2b, whose parent is still commit1.
>> 	• I want to rebase commit3 on top of commit2b.
>> The situation can be re-created with the following git commands:
>> git init
>> touch file1
>> git add file1
>> git commit -m "commit1"
>> git checkout -b branch2
>> touch file2a
>> git add file2a
>> git commit -m "commit2a"
>> git checkout -b branch3
>> touch file3
>> git add file3
>> git commit -m "commit3"
>> git checkout branch2
>> git rm file2a
>> touch file2b
>> git add file2b
>> git commit -a --amend -m "commit2b"
>> git checkout branch3
>> git rebase branch2
>> 
>> Expected: `git log branch3` shows commit1-commit2b-commit3
>> Actual: `git log branch3` shows commit1-commit2b-commit2a-commit3
> 
> I think this behavior is by design: rebase needs to find the common ancestor between branches. When you do “commit —amend”, it actually creates a new commit based on commit1 (nothing is overwritten). Now the common ancestor of branch 3 and branch 2 becomes commit1. Therefore rebase will replay both commit2a and commit3 over branch2 (whose HEAD is commit2b).
> 
> In short: rebase and commit —amend usually do not work very well together.

I would not say this way.  Sometimes git is smart enough that the commit was amended and will do the right thing by default.  However, the power of rebase comes with its command line options.  The most useful and what I use basically all the time is '-i' (or '--interactive') option.

In Junxiao's example, if you replace your last command with

    git rebase -i branch2

You will be given a list of what rebase operation is planning to do.  You can simply remove the old commit and everything will be done as you would expect.

* * *

At the same time, for this specific example, "cherry-pick", as suggested by Spyros is more appropriate (git rebase is just a wrapper for cherry-pick's)

Just a few other helpful commands that needed during complex rebases:

    git rebase --abort  # abort rebase session (in case something went wrong)
    git rebase --continue # this is already suggested in the prompt usually to continue rebase operations

Similar commands exist with cherry-pick

    git cherry-pick --abort  # abort cherry-pick (in case you don't want to resolve conflicts right away)
    git cherry-pick --continue # continue after fixing conflicts

* * *

Now. One of the powerful mechanisms of git: conflict resolution.  They are not scary and (usually) relatively easy to solve, provided the right tools are used.  (The right tools depends on the platform, but they exist on every platform.)

When conflict happens, either during any merge or during rebase operation (which is internally performing merge), you will see the conflict in `git status` either as "both modified", "remote deleted", or some other similar statement

To automatically go over each conflict, you can simply type**

    git mergetool

**
On OSX: the tools that best worked for me is "opendiff"   `git config --global merge.tool 'opendiff'`
I haven't used on Linux, but from what I looked online, good tools are kdiff3, emerge
For more available tools, you can check `git mergetool --tool-help`

Mergetool will prompt for each conflict, open GUI window for 3way merge.  With opendiff, it is a matter of clicking right/left/down arrows, followed by saving and quitting the app.

* * *

Another suggestion for everyone using gerrit, please play with Git Branching game (http://pcottle.github.io/learnGitBranching/).  It really teaches about rebase, rebase -i, cherry-pick and a few other techniques that are really useful when performing advanced git operations that are needed with gerrit.

* * *

One of the primary tools I'm using to understand history of git commits is "gitx" (OS X only, unfortunately: http://rowanj.github.io/gitx/).  Similar function is provided by git's own gitk and many other 3rd party (free and non-free) gui clients available (https://git-scm.com/downloads/guis).  In terminal, exploring git history (with branch graph), can be done either

     git log --graph --oneline

or with 3rd party `tig` command (can be installed from apt/brew/macports)

     tig        # will show just current branch and related information
     tig --all  # will show all branches

---
Alex

>> 
>> git doesn't seem to recognize that commit2b is a replacement of commit2a, and therefore keeps both.
>> This happens only if there's no conflict between commit2a and commit2b.
>> When there's a conflict, git would tell me to run `git rebase --skip` which would give the correct results.
>> 
>> If Alex or another git guru can help me solve this problem, I would be happy to start using unmerged parent commits.
>> 
>> Yours, Junxiao
>> _______________________________________________
>> Nfd-dev mailing list
>> Nfd-dev at lists.cs.ucla.edu
>> http://www.lists.cs.ucla.edu/mailman/listinfo/nfd-dev
> 
> _______________________________________________
> Nfd-dev mailing list
> Nfd-dev at lists.cs.ucla.edu
> http://www.lists.cs.ucla.edu/mailman/listinfo/nfd-dev

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 841 bytes
Desc: Message signed with OpenPGP using GPGMail
URL: <http://www.lists.cs.ucla.edu/pipermail/nfd-dev/attachments/20150908/fb582355/attachment.bin>


More information about the Nfd-dev mailing list