The irony of this behaviour is that it is both motivated by and the root cause of horrific merge sessions tying up multiple developers for days at a time.
No doubt the problems we'd had to do with missing changes was down to something we were not doing right, but the fact remains that it was all too easy for us to make those mistakes.
The zip file approach doesn't appeal to me so I've recently been using Git as an intermediate source control system to give me lightweight branching and the ability to make very fine-grained commits without trampling all over my colleagues' work.
I'm really enjoying Git (though I do intend to try Mercurial for comparison, and because I like Python) and something I did today made me want to write about it.
I'd been making changes to a COM-heavy codebase to try to fix a bug that had been, well, bugging me for days and when I finally had the breakthrough it occurred to me that some of the things I had tried may not have contributed to the fix (I'm normally more scientific than this but that's COM for you -
REGDB_E_CLASSNOTREG
doesn't necessarily mean that the class is not registered).Anyway, to cut what's becoming a long story short, I wanted to go back to the state of the code that "should have" worked, and selectively reapply the changes I'd made to ensure I was committing a minimal sufficient set back into TFS (to reduce merge headaches for my colleagues). What I was really impressed with was how easy and fast this sort of operation is with Git.
First, you rename the current branch (
master
, in my case) containing the whole set of changes, call it bug-fixed
:git branch -m bug-fixed
Next, you read the log to find the commit that corresponds to the point I started making the changes (this is where you're grateful you make regular, fine-grained commits):
git log --pretty=oneline -4
Note: the
oneline
option makes reading the commit signatures easier and -n
specifies the last n
commits - I knew it was only three or four commits ago.Having found the commit you want, you check it out using just enough of its signature to disambiguate:
git checkout 2adff2
And finally you create a new
master
branch, using the current state as a starting point:git checkout -b master
This very short (and quickly executed) sequence sets your
master
branch back in time to the appropriate commit, preserving the later changes in a named branch - genius, do that in TFS! (There are probably people who can but I'm not one of them.)Furthermore, selectively applying the changes from the newly renamed
bug-fixed
branch couldn't be easier:git checkout BRANCH [FILES]
pulls the versions of all the files specified by the space delimited list of files
;
(you can also use wildcards like *.h ) into your current branch. So to just bring over changes to some_class (declared in some_class.h, defined in some_class.cpp) from bug-fixed you'd do:git checkout bug-fixed some_class.*
Just bear in mind that as well as bringing them over, it also adds them to the index so they won't show up in
git diff
you have to use
git diff --cached
I intend to give git-tfs a try at some point but I'd also like to investigate using hooks to manage interaction between a central Git repository and a TFS server.