Git and Visual Studio are awesome together. For most commands, I don’t have to worry about using Command Prompt and leaving the slick UI of the IDE. It’s great to make a change, commit, and sync changes in Visual Studio within seconds. Yesterday, I was working on subtrees in Command Prompt, and right when I added a project to my repo in Command Prompt, the solution file showed up automatically in Visual Studio (read on for more info). How cool is that? But there are some days when using command-line is easier and more liberating than the limitations of just the IDE. Through some searching around and experimenting, I’ve found a few tools of Git that may make debugging, multitasking, and recovery easier:
Ever have those pesky bugs that were introduced somewhere between commits #59-163? Bisect is a great tool to find that first commit where a bug was introduced using a binary search. Sure, there may be a more efficient way of debugging, but at least this is fun and impressive.
The idea of this tool is to call bisect with a good (working) commit and a bad (non-working) commit. Then, Git moves the HEAD to a commit directly between the two (bisecting the commits). You reload your application, check it, and give it a good or bad response. Repeat this process until you find where the first commit was that this error appeared.
$ git bisect start
$ git bisect good <working commit>
$ git bisect bad <non-working commit>
$ git bisect good
$ git bisect bad
This command allows you to capture the delta of a commit and apply it to another branch with a new commit. Checkout the branch that you want to add the commit to, then do a cherry-pick on the hash of the commit you want to copy to the checked-out branch.
$ git cherry-pick <commit-name>
$ git checkout master
$ git cherry-pick C4
Switch between branches without committing work. Your data is saved on a stack of unfinished changes, and you can go back to it whenever you want. For those TFVC users, this is like a shelveset. Type in “list” to view all stashes, “pop” to apply the stash and remove it from the stack, and “branch” to create a branch from that stash.
$ git stash
$ git stash list
$ git stash pop
$ git stash branch <branch-name>
Recovery with Reflog
Oh no, you accidentally hard-reset one of your commits! Fear not, unless it’s been over two weeks (garbage collector already has removed it), you can get it back. Run the reflog command to find the SHA-1, then do a merge/cherry-pick/branch to recover that commit.
$ git reflog
Submodules and Subtrees
Both of these allow you to keep and use a separate Git repo as a subdirectory of another Git repo. They both have their advantages, it just depends on your needs.
Subtrees are especially cool and generally have more advantages over submodules. I tested subtrees out with a project that had a subtree has a dependency. It was just awesome when I could make changes to both solutions and push separately to different remotes. Some commands with subtrees:
$ git remote add <remote name>
$ git subtree add –-prefix= <new folder> <remote name> <branch>
$ git subtree push –-prefix= <folder> <remote name> <branch>
$ git subtree pull –-prefix= <folder> <remote name> <branch>
Bonus: Interactive Demo
Lastly, a quick shout-out to Shad on our team for finding this interactive online tutorial on Git basics. Check it out even if you’re a pro at Git: http://pcottle.github.io/learnGitBranching.
Pro-Git Book and Documentation