This article was last updated on July 29, 2024, to add sections for security and using Git Diff with other Git Commands.
Introduction
Git can be thrilling and, at the same time, intimidating as well. Don't worry, we are here to make things easier for you. Today, we're exploring Git's 'git diff'
command, which developers use on a daily basis.
This powerful tool helps you track changes throughout your working directory, commits, and branches. We will cover everything from fundamental usage to advanced capabilities like using regular expressions, highlighting changes in one line, and branch comparison using two- and three-dots. Let's unravel git diff's mysteries!
Steps we'll cover:
- Basic Usage of Git Diff
- Basic Example
- Advantage Usage of Git Diff
- Git Diff using a regular expression
- Highlighting Diff Changes in one line
- Git Diff Best Practices
Basic Usage of Git Diff
The git diff command shows the code changes between two commits or between the current repository and an earlier commit. This command displays changes indicated by file headers and metadata for changed files.
Specifically, this command allows you to accept two input data sets and output the differences between them. This command executes a diff function against a Git data source. It is commonly used in conjunction with git status and git log to analyze the condition of a git repository.
The syntax for the git diff command is as follows::
git diff
The git diff command displays any uncommitted repository modifications by default.
We can view the lines that have been removed from our original file, as well as any lines that have been added or modified. git diff
is frequently used to compare branches in a Git repository.
Basic Example
Let's create a simple test repository and compare changes between our working directory and the last commit using git diff
:
Explanation:
We will create a repository using “
mkdir
” command.Now we will utilize cd command to move to the repository we created.
By using the touch command, we will add and modify a test file with name “
testDiff.txt
”.We need to add content to the "
testDiff.txt
" file, so we have passed the string "This is a Tech Guide for git diff" to the text file."
git init
" command creates a blank Git repository - basically a .git directory."
git add testDiff.txt
" command will add testDiff.txt to the staging area. This is the area where the files will be added in the next commit.In this step, we have committed our changes by using “
git commit
”. When callinggit commi
t, it is required to include a message. The message should be a short description of the changes being committed. Through the option -am, you can add and create a message for the commit in one command.
Note that If we execute git diff at this stage, there will be no result. This is perfectly fine, as there are no changes in the code repository to display.
Now we will change the contents of testDiff.txt
file in our working directory to start experimenting with diff output:
- When we Execute this command, it will change the content of
testDiff.txt
file. Once this file is modified, then we can be able to see the difference and analyze the output.
Now let's execute "git diff
" command and analyze the results:
Explanation:
- It tells us which files are being compared in the diff. We are comparing the "
testDiff.txt
" file in the current version of the code to the "testDiff.txt
" file in the last committed version of our code.
A – Old version of the file
B – New version of the file
This line shows some internal Git metadata. The numbers in this output match to Git object version hash identifiers. 100644 is an internal file mode identifier.
A diff doesn't show the whole file. It shows only modified lines. It is standard naming convention that Git assigns a minus sign (-) to the A variant of the file and a plus sign (+) to the B variant of the file.
The fourth line shows the symbol @@ followed by -1 +1. These are called 'hunks' in Git terminology. Hunks in a
git diff
provide a summary of the changes. In our example, -1 +1 implies that the changes started from the first line in both the original file and the new state, with a default context range of one line, indicating that one line has been altered.
Advantage Usage of Git Diff
Git Diff using a regular expression:
We can use the git diff command with the regular expression to highlight only specific changes that match the regular expression in the difference between the current version with the previous version.
Syntax: git diff --word-diff-regex=\<regex here\>
For example, we have made a most recent change in our "testDiff.txt
" file by adding a line "The current feature we are testing is the git diff
with regular expression." Now, we will execute the command with the regex "Regular". The output should highlight the specific change provided to regex in the difference from the previous version.
Explanation:
This is the difference in content from the last commit; this content is currently in the staging area.
This is the highlighted change that matches the regular expression in the content differences between the previous and current versions.
Highlighting Diff Changes in one line
Another helpful option is --color-words
. Instead of the "classic" display mode in diffs, sometimes we are interested only in viewing the exact words that have changed instead of viewing entire lines.
Syntax: git diff --color-words
Explanation:
- Now the changes can be seen in one line only. The word in red depicts that it has been deleted from the original file.
Git Diff Between two branches
Often, we are interested in finding the differences between the two branches. There are two ways to achieve this in Git. The first method involves running the 'git diff
' command with two dots between the branch names, and the second method uses three dots instead.
Git Diff Between two branches (Two Dots Method)
Syntax: git diff branch1..branch2
This will show you all of the commits that branch2 has that branch1 doesn't have.
For example, we have two branches: Main & Feature
Now we will Check the difference between the two branches by using the following command: git diff main..feature
Both branches have a file "testDiff.txt
", but with the different content
This command checks the difference between the tips of the two branches (HEAD). Besides, it will show you what's different between the two branches.
Explanation:
A version: The main branch contains "
testDiff.txt
” file with the content "This content is present in the main branch".B version: Feature Branch contains "
testDiff.txt
" file with the content "This content is present in feature branch".
Here is a visual explanation of evaluating the difference between the main branch and the feature branches using the two dots command:
Git Diff Between two branches (Three Dots Method)
Syntax: git diff branch1...branch2
Three dot diff shows changes between revisions A and revision B starting at the last common commit. This is useful for viewing pull request diffs. git diff
with 3 dots compares the latest commit on your feature branch with that common ancestor commit, which is essentially the point from where you branched off to create your feature.
For example, we have two branches: Main & Feature, but before creating these branches and coming to the branch comparison section, we were on git diff
Between staging area and last commit" section, so the common ancestor commit was about staging area. Let's execute the 3 dot command to check the difference.
Explanation:
A version: This was the last commit we made before creating the feature branch, and it is the common ancestor between the main and feature command.
B version: This says that the only difference between the main and the feature is the new line I added in the testDiff.txt file of the feature branch.
Find below an illustration that shows how to check the difference between the main and feature branches using the above command (3 Dots):
Git Diff Best Practices
Git Diff Between staging area and working directory
We can also compare our changes in the working directory with the changes added in the staging area. For this purpose, we can use the following command:
git diff
Let me give you an example by adding the change to the staging area and then modifying the same file in the working directory to compare the changes between the staging area and the working directory:
Added the content in file "testDiff.txt
" for staging area.
Now move the changes to the staging area by using the command "git add
"
For comparison, now we will make a change in "
testDiff.txt
" which is in the working directory.By executing the command "
git diff
" we will get the comparison result of the staging area and working directory.
Red: Represent the content that was added in the staging area
Green: Represent the content that was changed in the working directory.
Git Diff Between staging area and last commit
Suppose you're about to lock in your changes with a commit. But wait, you want to see what differences there are between the changes you've staged and the most recent commit, right? No problem at all! By simply tacking on the '--staged
' flag, you'll be able to make this comparison in a snap.
Syntax: git diff –staged
Now let me explain it through an example:
Explanation:
We have added a new line to the existing file "
testDiff.txt
".Here we have added our changes to the staging area.
Now, we will execute the command git diff –staged
to view the difference between the staging area and the last commit.
Explanation:
A version: last commit containing the line "This is the diff we are adding to the file" in testDiff.txt.
B version: Staging area which differed from the last commit with a new line "Adding this new change for staging area" in testDiff.txt.
Git Diff Between two commits
If you're aiming to compare files between two specific Git commits, all you need to do is specify the 'ref' that points to the commits you're interested in. A 'ref' could be a commit hash or even 'HEAD', which represents the current branch you're working on.
Compare Using Commit hash(any specific commits)
Syntax: git diff \<commit_hash\> \<commit_hash\>
Now we need to fetch the hashes of the commits we want to compare using git diff
. For that purpose, we will use another command "git log --pretty=oneline
".
Let's assume we are going to compare these two commits [hashes above in 1 & 2]. We will execute the following command:
git diff 21d752987e7f507494439a599a02a105039b4125 60b1649d99710436fb56991b1120736d5e33c63e
By executing this command, we'll be comparing two distinct commits. The output will display the differences between these two instances, effectively showing us what has changed within the files.
Compare Using Head (Last two commits)
If you want to find the differences between the two most recent commits, you will use the following command:
Syntax: git diff HEAD HEAD~1
This command will compare the most recent commit (HEAD) with the commit before it (HEAD~1). The output will show you the differences between the two commits.
Explanation:
(HEAD) represent the most recent commit
(HEAD~1) represent the commit before (HEAD)
Using Git Diff with other Git Commands
Using Git Diff with Git Blame
We previously delved into how we can use 'git diff
' with Git hashes to compare two specific commits. However, remembering the exact hashes of the commits we want to compare can be tricky. That's where 'Git blame
' comes in handy. We can use it to retrieve the hashes of the commits we're interested in and then use 'git diff' to draw a comparison.
For example, we want to see the commit hash, author, and timestamp for the last change made to “testDiff.txt
” file.
You can use commit hash to compare different commits using git Diff (Sample Below).
Using --base
with Git Diff
Merge conflicts mostly arise when several developers work on the same codebase. Running git diff
can point out conflicting changes and help you address them smoothly:
git diff --base file.txt
This command compares the conflicting file with the base version, making the conflicts clearer to understand and solve.
By the insertion of these additional sections, this article is going to be a more complete guide on how to use git diff
, which I believe should not only deal with technical usage but practical application.
Security Features with Git Diff
Now, I'd like to share a few thoughts on the security measures we can put in place to enhance our Git workflow:
Pre-commit Ho
I will be able to use Git hooks in order to make automatic checks of security issues before commits. For instance, pre-commit hooks can check for sensitive data such as API keys or passwords.
# .git/hooks
if grep -q "API_KEY" *.js; then
echo "API keys found in the code. Please remove before commit."
exit 1
fi
Commit Signing
We can sign our commits even with GPG keys, making sure that our commits are authentic and helping in the verification of the trusted source of commits.
git config --global user.signingkey YOUR-GPG-KEY-ID
git commit -S -m "Your commit message"
Regular Audits
Periodic auditing of the codebase can be done through the use of the git diff
tool to identify any security glitches in the code and fix them during checks. We get to see what changes are brought in and what is fishy.
git diff HEAD~5
The previous 5 commits are compared to the state currently being looked at, to review changes within recent history.
Access Controls
The access controls on our repositories need to be strict, in a manner such that only the rightly authorized people possess the capability of pushing changes. This can be governed within GitHub and GitLab access controls and other hosting services for Git.
Those are the steps that can help us maintain a more secure codebase and prevent a potential breach of security.
Conclusion
In this article, the 'git diff
' command was thoroughly examined. We've tried to uncover all the different commands for maximum utilization, from basics to advanced tricks to best practices. 'git diff
' is just one command in Git's enormous ocean. Don't be afraid to try out all the coding examples provided in this article.
After all, the more tools in your developer's kit, the better prepared you'll be to handle different challenges coming your way. Keep coding, and keep exploring different Git articles on our blog.