In Git, you can use the git diff command for comparisons. This command is very powerful and flexible, and it covers a lot of ground, but today we’ll be narrowing the scope down to the “git diff tags” use case.Â
In this post you’ll learn how to compare two tags in Git. We’ll cover some fundamentals about both the git diff command and tags, so don’t worry if you’re not familiar with these terms.Â
By the end of the post, you’ll understand what tags are, how to diff them, and how to interpret the output of the diff itself.Â
Does your team struggle with software audits? Is it a mess of screenshots and spreadsheets?
Learn how to automate itRequirements
There are just a few requirements to follow along with this post:Â
- You should be comfortable working with the command line.
- You should have Git installed on your system.
- You should be familiar with some basic Git commands.
We don’t make any assumptions regarding your choice of operating systems. I’ll be testing the commands I write on both Windows and Linux (Ubuntu), but I expect them to work on macOS as well.Â
git diff Tags 101
Let’s start by answering some fundamental questions so we’re all on the same page.Â
What Are Git Tags?
Git tags are labels or marks you can add to a commit. Think of them as a friendlier name for a commit. If you mark a commit with the tag “good-spot,” then you can use “good-spot” to refer to that commit instead of, say, a854d19
.Â
People often use tags for marking software versions. So, at the exact spot where a new release is cut, you bump—that is, increase—the version number and then add a tag to that point.Â
Here’s a quick example of tags in use:
$ mkdir demo
$ cd demo
$ echo hello > file
$ git init
$ git add .
$ git commit -m "create file"
$ git tag first-commit
In the example above we created a new repository, added a commit, and then added a tag to it. Now, running the git tag
command will list “first-commit” as an output:
$ git tag
first-commit
What are git diffs?
To understand git diff, let’s first make sure we know what diff is.Â
According to Wikipedia:Â
In computing, the utility diff is a data comparison tool that computes and displays the differences between the contents of files.
So, we can say that git diff
is just Git’s implementation of the diff utility. With this command you can compare two commits, branches, and, of course, tags.Â
Let’s see a quick example of git diff
in practice, using the same repo from the previous example:Â
$ echo more text >> file
$ git diff
We simply append more text to the existing file and then run the diff command. If you’re following along you should see something like this:
diff --git a/file b/file
index 907cd4b..29cf517 100644
--- a/file
+++ b/file
@@ -1 +1,2 @@
hello
+more text
If that output looks confusing, don’t worry - we’ll explain it in more detail later in this post. For now, understand that it just says the line “more text” was added as the second line of the text file.
Git Diff Tags: How To Use It In Practice
You now understand what tags are and what diff is. It’s time to put the two together!Â
First, let’s commit the change made during the previous example:
$ git commit -am "append to the file"
Run git log --oneline
, and you’ll see an output like the following:
$ git log --oneline
0f07e99 (HEAD -> main) append to the file
8ce58eb (tag: first-commit) create file
The only difference is that the commit hashes (the alphanumeric commit identifier you see at the start of the line) will be different from mine.Â
Now let’s do three things:Â
- append yet another line to the file
- commit that change
- mark the commit with a new tag
The following commands accomplish the above:
$ echo another line >> file
$ git commit -am "edit the file"
$ git tag new-version
Running git tag
now shows the two tags:
$ git tag
first-commit
new-version
Now that we have two tags, let’s compare them. Run the following command:
$git diff first-commit new-version
The output should look like this:
diff --git a/file b/file
index 907cd4b..b8fe3f1 100644
--- a/file
+++ b/file
@@ -1 +1,3 @@
hello
+more text
+another line
Basically, here it says that the two tags differ regarding the file called file
. The file has two more lines in the version pointed at by the most recent tag.Â
Keep in mind that the order is relevant regarding git diff
. Let’s run the command again, this time swapping the order of the tags:
$git diff new-version first-commit
Here’s the result:
$ git diff first-commit new-version
diff --git a/file b/file
index 907cd4b..b8fe3f1 100644
--- a/file
+++ b/file
@@ -1 +1,3 @@
hello
+more text
+another line
As you see, now it shows that the two last lines have been removed! You might have some reason to look at the changes this way, but if you want the comparison to take chronological order into account, you must also provide the tag names in the correct order.Â
Understanding the Output of git diff
The output of git diff can look confusing at first. However, it’s not hard to understand once you know what each bit of information means. So, let’s cover that. We’ll examine the output of running git diff first-commit new-version, line by line.Â
For reference, this is what the output looks like:
$ git diff first-commit new-version
diff --git a/file b/file
index 907cd4b..b8fe3f1 100644
--- a/file
+++ b/file
@@ -1 +1, 3 @@
hello
+ more text
+ another line
What Is “A” and “B” in git diff?
The first line of the output is this:
diff --git a/file b/file
The line above indicates the file that we’re comparing. The name of the file is simply file. A and B are prefixes, indicating the comparison’s source and destination. It’s possible not to show prefixes:
$ git diff first-commit new-version --no-prefix
diff --git file file
index 907cd4b..b8fe3f1 100644
--- file
+++ file
@@ -1 +1,3 @@
hello
+more text
+another line
You can also choose different prefixes for the source, destination, or both:
$ git diff first-commit new-version --src-prefix=start --dst-prefix=end
diff --git startfile endfile
index 907cd4b..b8fe3f1 100644
--- startfile
+++ endfile
@@ -1 +1,3 @@
hello
+more text
+another line
What About Those Numbers?
The second line of the output is this:
index 907cd4b..b8fe3f1 100644
Here, 907cd4b
is a sha1 hash identifying the first version of the file. b8fe3f1
identifies the latter version of the file. Finally, 100644
represents the file’s mode, indicating it’s a normal, non-executable file.
Plus and Minus Signs
Next, we have those two lines:
--- a/file
+++ b/file
Those are markers. They indicate that when you look at the next section, the minus sign will correspond to the first file while the plus sign will point to the latter version.Â
Chunks
The next section of the diff output is called chunks. They indicate the exact lines of the file that were changed between the versions:
@@ -1 +1,3 @@
The -1
refers to the first file—which is marked by the minus sign, remember? This indicates that the first line of what we’ll see next is present in the first version of the file.Â
The +1,3
part refers to the second version of the file, which is represented by the plus sign. This indicates that the first line of the following output is present in the second version of the file, and then it has a total of three lines that are present in the file as well. That makes sense since the most recent version has two more lines than the first one.Â
Now we have the actual differences:
hello
+more text
+another line
The first line is present in both files. The second and third lines are present only in the second file, which is represented by +1,3
. The plus signs at the start of the line indicate that those lines were added.Â
Git Diff Tags: Useful Options
Let’s now explore some more ways to use this command.Â
Showing Information About Files Changed
In our examples so far we changed only one file. A commit is likely to touch many different files in a real-world scenario. A comparison between two tags that are far apart is bound to result in a lot of output. You’ll often want Git to list all the changed files instead of showing the actual differences. For this, you can use the --stat
option.
For this example let’s add two more commits. First, we’ll append again to the existing file:
$echo even more text >> file && git commit -am "another line"
Then, let’s create a new file and commit that as well:
$ echo new file > file2
$ git add .
$ git commit -m "create new file"
Finally, let’s create a tag:
$git tag number3
Then, let’s run the command:
$git diff first-commit number3 --stat
This results in the following output:
file | 3 +++
file2 | 1 +
2 files changed, 4 insertions(+)
Git says that two files changed, with four insertions. We added three lines to the first file between the first tag and the latest one. The inclusion of the new file counts as one line.Â
Without the --stat
option we get the full diff, which is quite busier than what we’ve seen before:
$ git diff first-commit number3
diff --git a/file b/file
index 907cd4b..43044eb 100644
--- a/file
+++ b/file
@@ -1 +1,4 @@
hello
+more text
+another line
+even more text
diff --git a/file2 b/file2
new file mode 100644
index 0000000..fa49b07
--- /dev/null
+++ b/file2
@@ -0,0 +1 @@
+new file
As you can see, the result now contains two entries, one for each file. Regarding file2, it’s represented by /dev/null in the first tag. That happens because the file didn’t exist back then.Â
Diffing Only One File
What if you want to compare two tags but are only interested in a single file? It’s possible to filter for a single file or folder. Just add two dashes and then the path to a file or folder. In our case, let’s say we only wanted the diff for file
. Here’s what we’d do:Â
$ git diff first-commit number3 -- file
The line above results in the output below:
diff --git a/file b/file
index 907cd4b..43044eb 100644
--- a/file
+++ b/file
@@ -1 +1,4 @@
hello
+more text
+another line
+even more text
Conclusion - diff tags are useful and fun :)
Comparing versions of files is a core feature of a version control system. Git is no exception to that. This post shows us how to use the git diff command to perform a diff between tags. You’ve learned about tags themselves, what they’re used for, and how to interpret the output of the diff command.Â
Where should you go now? I have two suggestions. First, continue exploring the diff command. Try to make different changes—for instance, remove lines—and see how the output of the command behaves. You can also explore some tools to make your diff viewing experience better. On Windows, WinMerge is a nice option. Meld is also interesting and available both for Windows and many Linux distributions.