A place for spare thoughts


GitTfs rebasing workflow. Is it possible?

Filed under: git, git-tfs — Ivan Danilov @ 06:55

Here is the issue on GitTfs about some complexities in usage. The point is GitTfs allows you to take a feature branch and put it into the TFS in single checkin. On the git side this action produces merge commit with two parents: one for previous commit fetched from TFS and another from your feature branch. If you want to have fine-grained history on TFS side – you have a problem.

So what could we do with it?

I’ve just finished a patch that allows to perform fine-grained workflow more-or-less painlessly. The idea is new option to checkin command, namely –rebase-workflow or just -r.

Lets name for simplicity commit being checked into TFS as ‘source’ and fetched afterwards as ‘result’. Source belongs to feature branch that we want to check into TFS commit-by-commit.

So what -r key is supposed to do? First and the most important result of -r is that it suppresses marking result as merge commit. Just skips assigning source as parent. So after checkin we’ll have two separate branches, and result will actually contain all changes from source but it won’t be shown in the graph.
See the diagrams below:

      \<-- B <--- C


  A <----- B'
    \    [tfs]
      \<-- B <--- C

Here B’ has all changes from B.

Just to compare with default behavior:

  A <---------- M
    \         /
     \       /
      \<-- B <----- C

M is merge commit and B is original. They are just the same change from A most of the time and it is confuses history very much.

So how could we going to turn two diverging branches into linear history? With a rebase of course.
We could take remaining of the local branch (so it is C actually) and rebase it to the B’. It will go smoothly as we are just applying clean patch essentially. Thus B becomes (most likely – if there were no third branches spawned from feature branch) orphan commit and will go away. Which is ok as we have all changes from it in the B’. And it is exactly what -r key tries to do for you.

I did some testing (simplest actually and with some conflicts/interfering with native TFS client) on my local TFS server and it seems working well and producing much more understandable history. But I’m not an expert in git so I could miss some cases. Currently I only check with rev-list that source doesn’t have parents which are not parents of HEAD thus we could apply source..HEAD to result smoothly.

Intended workflow is like that:

git checkout -b local
# make changes
git commit -m 'blah'
# make changes
git commit -m 'blah2'
git tfs fetch
git rebase tfs/default

git tfs checkin -r -m 'blah goes to tfs with rebase' HEAD^
# thus we are sending just first commit leaving history clean

git tfs checkin -r -m 'blah2 goes to tfs also'
# here source is HEAD so we can omit it

git checkout master
git merge tfs/default
git branch -D local

As a result you should have just a linear history in git consisting from TFS commits.

So the comments/objections/suggestions are welcome.

Branch with corresponding changes is here

UPDATE: currently rebase-workflow branch is integrated in mainline of the git-tfs project in form of rcheckin command. So the branch mentioned above is no longer exist.


Leave a Comment »

No comments yet.

RSS feed for comments on this post. TrackBack URI

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )


Connecting to %s

Blog at WordPress.com.

%d bloggers like this: