Comparing things in Git

A look at some Git techniques for comparing things


In the last article, we saw a way to find out if a fast-forward merge is possible in Git. In this one, we'll look at some common commands you can use to compare things in Git.

MODX logo

If you work with Git regularly, you probably know most of these. If you're new to Git, some of these may be unfamiliar. Either way, you might find something useful here that you didn't know.


Which Files in my working directory have been changed

This command will list the changed files:

git status

I've created an alias in the terminal emulator I use (Cmder) that does the same thing:

gs

Cmder is like shelling out to the Windows command line but with the addition of color, cut and paste, and the option to edit and then execute a previous command. Cmder is also more "Unix-like", with built-in commands like ls, grep, curl and history. In PhpStorm, I can easily shell out to my terminal by clicking on the "Terminal" button at the bottom of the screen. Then, I can issue Git commands without leaving my place in the editor. How you create aliases depends on which terminal program you use. If you use PhpStorm, this page explains how to use a custom terminal program.

Git Status will show all changed files (with the exception of ignored or excluded files). If a file is not tracked by Git, it will still be listed, but will be identified as untracked. Files specified as ignored or excluded will not be shown at all, even if changed.


Which Files Changed in Previous Commits

git whatchanged

This command will show a list of your commits, starting with the most recent commit and working backwards, with a sub-list under each commit showing which files were changed.


Which Files are Different Between Two Branches

If you are on the bugfix branch and want to compare it to the dev branch, you can type git diff dev. If you want to compare to other branches, you can type git diff branch1 branch2. If you want to compare your dev branch with what you have on a remote repository like GitHub, you can type git diff dev origin/dev.

These commands work a whole lot better if you have a diff/merge program that shows you the difference. Git by itself will show you a diff file like what you see when looking at a specific commit on GitHub. This can be pretty frustrating if there are a lot of differences and/or a lot of files have been changed. A good program will show you the two files side-by-side, with color highlighting of the differences, and an option to move changed code either way between the files. As you would expect, the file you list first on the command line (or the current branch's file) will be shown on the left.

For Windows, WinMerge (free) is tough to beat. For IOS, there are a number of options, but at this writing, none of the free ones are as capable as WinMerge.

After installing a diff/merge program, you'll have to tell Git where it is.

When running git diff, you can use the asterisk (*) as a wild card. This command will show your the diff only for files that have tye word "symlink" in their file names:

git diff *symlink*

This also works with git add. If you have a good terminal program, you can do git diff *somepattern*. Then, if you're ready to commit you can hit the up arrow to edit the last command and change diff to add. Then you can do this, and only those files will be committed:

git commit -m "Some message"


When Diff is Impractical

Sometimes, a diff/merge program is just what you want, it shows you the exact differences between the files in each branch. Sometimes, though, you don't want to page through the all the files (including created or deleted files), you just want to know which files they are. This is one of my favorite Git commands, and for a long time, I didn't know it existed:

git diff --name-only dev
git diff --name-only branch1 branch2
git diff --name-only dev origin/dev

This command is really helpful when you just want to know which files have changes in your current branch when compared to another local branch or a remote branch, especially when a lot of files have changed.


Which Files Changed in the Last Commit

If you want to know which files changed in the last commit, you can use git whatchanged as mentioned above, but you can also do this:

git diff --name-only HEAD HEAD~

HEAD points to the most recent commit. HEAD~ points to the commit before that one. This command will not list changes in the working directory because they haven't been committed yet. The following command does the same thing, but adds in the changed files in the local directory.

git diff --name-only HEAD~

When you leave out the first diff target, Git assumes that you mean the current working directory, so the command above is comparing your working directory with the commit before the final one.

Actually, HEAD~ is a shorthand for HEAD~1. The number tells Git how many levels you want to go up. If the number is missing, Git assumes it's 1. So if you make three commits in sequence (let's call them A, B, and C). C, the most recent commit, is the current HEAD, B is its parent commit, and A is its grandparent. So, git diff HEAD HEAD~1 compares C with its parent, B. If you want to compare further back, git diff HEAD HEAD~2 compares C with its grandparent, A, and git diff HEAD~1 HEAD~2 compares HEAD's Parent, B, with its grandparent, A.

With the commands above, ~ and ^ are supposed to be equivalent. So HEAD~ andHEAD^ (and their variants) should do exactly the same thing. On my machine, though, only ~ works. I suspect that it's a quirk in my particular setup, but if one doesn't work for you, try the other one.

If you want to compare the files that have been staged for committing with Git Add against the changes that have already been committed you can add --cached or --staged (the two are equivalent) just after the word diff in any of the diff commands above. It can be combined with --name-only (or not).

git diff --cached --name-only HEAD~
git diff --cached HEAD~

Comparing any Two Commits

I seldom use this, but you can compare *any* two commits by using their SHA1 identifiers. Each commit in Git is identified by a long number, called an SHA1. They look like this: 6e1199df259f98ed5cfef65ffcfbe46a6d81f13b. You will see them listed after the word "commit" when you type git log or git whatchanged. When entering an SHA1 in a Git command, you don't need the whole number, just enough to let Git find it. Usually, the first four or five characters are enough. Git will tell you if the SHA1 fragment you enter is not unique, but it's never happened to me.

So, to compare commit 6e1199df259f98ed5cfef65ffcfbe46a6d81f13b with commit 78eed58e1fbe0a88ec51342ae15f7780429471c2, you could almost certainly do this:

git diff 6e119 78eed

This can be handy, say, when you want to find something you know you did last Saturday, but can't remember which file it's in. Typing git log will show you your commits with the dates they were made. You can pick a commit from late Friday and one from early Sunday and see all the changes you made during that period. Adding --name-only will just list the files you worked on, which might be enough to jog your memory.


Coming Up

In the next article, we'll at how to compare things in PhpStorm.



Looking for high-quality, MODX-friendly hosting? As of May 2016, Bob's Guides is hosted at A2 hosting. (More information in the box below.)



Comments (0)


Please login to comment.

  (Login)