Programming is more than just writing new code, it also involves constantly analyzing previously written code. Sometimes the code is understandable without any comments (that's good code), but that's not always the case. The code may raise questions. Why was it written this way, who wrote it, and when?
The change history helps answer these questions. If the commits are done well, i.e., they have a clear description, and each of them does exactly one complete thing, then the history becomes a powerful tool for code analysis. That's why it's so important to understand git philosophy and follow best practices when working with it.
Git provides a whole bunch of commands with lots of options to extract incredible amounts of information and show everything that's been hidden.
Git Log
You can carry out the simplest analysis using the git log
command. It shows a list of all commits made in a repository, sorted by date added (with the most recent on top):
git log
# Below is an incomplete output of the project history
commit 5120bea3e5528c29f8d1da43731cbe895892eb6d
Author: tirion <tirion@got.com>
Date: Thu Sep 17 18:04:19 2020 -0400
add new content
commit e6f625cf8433c8b1f1aaed58cd2b437ec8a60f27
Author: tirion <tirion@got.com>
Date: Thu Sep 17 16:14:09 2020 -0400
add INFO.md
commit 273f81cf2117044f1973ea80ce1067a94bea3f80
Author: tirion <tirion@got.com>
Date: Thu Sep 17 16:08:39 2020 -0400
remove NEW.md
# This output is shown via pager
From this output we can find out who did which commits and when. If the commits are well-written, then their description will make sense anyway. The formatting of commits is a separate topic that we'll look at later.
The git log
command has the rather useful -p
flag that immediately outputs all the diffs for each commit:
git log -p
# These are all commits with a full diff
# Press f to go forward, b to go back
# Exit view mode - q
Git Show
Each commit has an identifier, a "hash", which is a unique set of characters. You can use the hash to look at all the changes made within a single commit:
git show 5120bea3e5528c29f8d1da43731cbe895892eb6d
# Here outputs the diff between this commit and the previous one
diff --git a/INFO.md b/INFO.md
index d5225f8..40f51f1 100644
--- a/INFO.md
+++ b/INFO.md
@@ -1 +1,2 @@
git is awesome!
+new line
diff --git a/README.md b/README.md
index ffe7ece..00fd294 100644
--- a/README.md
+++ b/README.md
@@ -1 +1 @@
-Hello, Hexlet!
+Hello, Hexlet! How are you?
# I.e., what was changed by this commit
The commit hashes in git are very long and can be inconvenient to use. That's why the developers of git added the ability to specify only part of the hash. You just need to take the first 8 characters and place them next a command that works with commits:
git show 5120bea3
Most of the time you won't have to figure them out yourself; most git commands will print the commit hash in an abbreviated form, making it easy to use. This way of simplifying works well because even the first 8 characters will always be unique.
Git Blame
What if we don't know the commit, but we want to know who was the last person to change a certain line in a file? The command git blame <path to file>
is good for this. This command displays the file and next to each line shows who changed it and in which commit.
git blame INFO.md
e6f625cf (tirion 2020-09-17 16:14:09 -0400 1) git is awesome!
5120bea3 (tirion 2020-09-17 18:04:19 -0400 2) new line
It's important to remember that changing a line is not the same as adding a new one. It is quite possible that the programmer corrected a small typo, but the line itself was written by someone else. In any case, with an output like this, it's easy to go further and examine a particular commit.
Git Grep
The git grep
command looks for lines matching a specified line in all files in the project. This is a very handy command for quick analysis from the terminal. It's more convenient than normal grep
because it takes .gitignore into account and doesn't look in the .git directory, and it can also search through the change history:
git grep line
INFO.md:new line
# The i flag allows you to do a non-case sensitive search
git grep -i hexlet
README.md:Hello, Hexlet! How are you?
# Search in a specific commit
git grep Hexlet 5120bea3
# Search through history
# rev-list returns a list of commit hashes
git grep hexlet $(git rev-list --all)
GitHub
In simple situations, you can analyze a project on GitHub itself. It allows you to view the history of commits, changes in a particular commit, and much more.
Do it yourself
- Follow all of the steps in the lesson
- Try to see the history of the Hexlet Guides repository