In previous article, I explain how to revise local commits afterwards via Git. In this article, I explain how to find the commit which causes the issue when something went wrong.
Sometimes, I find that one function stop working all of sudden, but I don’t know when it’s broken. If I am the only developer, it maybe easier to track down the issue, but what if we have many people working on the same project and they add commits every day. How I can quickly identify which commit contains the bug? I know we should implement unit testing, so that we can find the issue as soon as someone commit new items
Find who modified the file in Git
In this case, I would like to track down when README.md file had “Change 2” line and who did it.
1. Run ‘type README.md’ and ‘git log –oneline –graph –all’ to check the latest situation.
2. When I see the commit comment, it looks like commit f9e666f seems to add the line. Run ‘git diff 1cf7510 f9e666f README.md’ to see the difference, and…. YES! the case closed.
3. Well, things are not as simple as this in the real world. So what else I can do? Run ‘git blame README.md’. The blame command shows all the changes for the item. The work “blame” sounds a bit scared to me though . Now I see commit f9e666f5 did change the file, who did the change and when it happened.
4. Run ‘git blame -L 3, 3 README.md’. The -L option filters the result by line number. First one is from, and second one is to. So in this case, I filtered the result which changes the line 3 to line 3 (so just one line) for README.md.
5. Blame also tracks down file name changes. Let’s try it now. Run ‘git mv README.md Read_Me.md’ to rename the file.
6. Run ‘echo “Renamed” >> Read_Me.md’ and ‘git commit -am “Rename README.md”’ to commit file name change.
7. Run ‘git blame Read_Me.md’ and it shows all history for the file including before renaming the file.
8. What happens if I delete the lines instead of adding? Let’s do it. Run ‘echo # VS_Git > Read_Me.md’ and ‘echo Change 1 >> Read_Me.md’, then run ‘git commit -am “Removed Lines from Read_Me.md”’.
9. Run ‘git blame Read_Me.md’ and I couldn’t see deletion changes.
10. Now what? Well, I can search it by using log command with -S option. Run ‘git log –oneline -S “Change 2”. This shows when it’s added or modified.
11. If you run ‘git log -p -S “Change 2”, then it shows you all the detail. From the log, the commit 1c79720 deleted the “Change 2” line from Read_Me.md.
Find who created the issue in VS
Next, do the same in Visual Studio.
1. In Solution Explorer, you don’t see Read_Me.md. Why? Because I just renamed the file in Git, and solution didn’t track it. Select the solution and press Shift+Alt+A to add existing item. Select Read_Me.md and add it.
2. Right click the file and select “Blame (Annotate)”.
3. VS takes ‘git blame Read_Me.md’ information and displays in GUI. If I select the line in the right pane, it gives me which line has been modified in right pane.
4. I couldn’t find –S option for log command via Visual Studio 2017. But I can still use compare feature to see it. Right click Read_Me.md again and click “View History”. Right click the latest commit and click “Compare with Previous”.
5. You see the changes. You can also select two history lines and compare them.
Find which commit contains bug in Git
By using blame or log with -S option, I could find out who and when modified a particular file. But often time, I even don’t know which file caused the entire issue. In that case, we can checkout each commit one by one to see which commit actually introduce the issue. What is the most efficient way to check this? I know the latest commit has issue. So shall I go back each commit? Or shall I start from middle of the entire commits to reduce the commits into half every time? Git provide a command which does it for us.
1. Run ‘git bisect start’, which starts the inspection operation. Then, run ‘git bisect bad’ to mark current commit has the issue.
2. Now time to find a commit which doesn’t have the issue and mark it as good. For now, I mark the first commit as good here. Run ‘git log –online’ to find the first commit and ‘git bisect good 728f37d’. Then Git “checkout” the commit in the middle. In this case, commit 3127d2f.
3. Run the application to see if it contains the issue. In this case, I mark this as good. Run ‘git bisect good’. Now Git checkout the commit between latest and commit 3127d2f, which is commit f9e666f.
4. Let’s assume I find the same issue in this commit, then I run ‘git bisect bad’ to mark this as bad commit. Now, only commit lest to inspect is commit 1cf7510, as commit f9e666f is bad whereas commit 3127d2f is good.
5. Assume again this commit was good, then run ‘git bisect good’. Then Git tells me that commit f9e666f is the first commit contains the issue, and it also shows me which items are part of this commit.
6. Run ‘git bisect reset’ to reset everything.
To run less command, I can run ‘git bisect HEAD 728f37d’, to let git the bad and good commit as bisect parameters.
Find which commit contains bug in VS
Unfortunately, I couldn’t find bisect support for Visual Studio. But, I believe everyone has unit tests and function tests so that you can see what’s wrong immediately when someone adds new commit !!
I barely use these features so far, as I have tests in-place or I am lucky enough so far. But bisect is one of the powerful tools to track down which commit has the issue.
By the way, this is the last article of the series at the moment, and the next series will be VSTS/GitHub and Visual Studio 2017. Please feel free to give me any feedback in comments area what’s good, bad or missing.