Imagine, you’re coming back to a project that has advanced by two months with various people coming and going. And it’s your job to figure it all out. Git has your back! Here’s how.
So, there sure are a lot of branches. After a git fetch
, you may want to start off with this one:
Where were the most recent changes made?
$ git for-each-ref --sort="-authordate:iso8601" --format=" %(authordate:relative)%09%(refname:short)" refs/remotes/origin 22 hours ago origin/topic/ipad 34 hours ago origin/topic/ipad-mini 34 hours ago origin/master 2 days ago origin/topic/2015-motoren 8 days ago origin/topic/mobile 8 days ago origin/topic/android 4 months ago origin/topic/2015-motoren-delhi
Based on this StackOverflow Answer. We’re going over the refs in refs/remotes/origin
which basically means “the branches of remote origin” We’re printing those branches with relative date, but sorting them by iso date.
You get a good idea, what branches have changed recently. No need to dig into a branch that hasn’t changed in four months.
Who was working on those branches anyway?
You might be tempted to answer this question with git log, but that gets you output like the following snippet, and i’ll show you a better way!
$ git log origin/topic/2015-motoren commit eff2017d61dar0659f43b0dv79ad5f1f13bd85e0 Author: Alice <alice@example.com> Date: Wed Sep 2 10:47:17 2015 +0200 amazing stuff commit 5af113f3es3f2981586b25e00806fe4d91ccb733 Author: Alice <alice@example.com> Date: Wed Sep 2 10:39:54 2015 +0200 preparing amazing stuff
Looks like a lot of amazing stuff happened. And we also see, who’s involved. The git log
command is powerful, and I use it a lot, but for the currenct question, it’s not the right tool. A nicer variation is the git shortlog
:
$ git shortlog -s -n --no-merges "origin/topic/2015-motoren@{2 months ago}"..origin/topic/2015-motoren -- 19 Alice 2 Bob
We get a nice list of people. -s
is for “summary” which prints only the name (try without the -s
, that’s also highly useful!), and the -n
sorty by commit number. For this list, I also like --no-merges
as those usually don’t introduce new code. We’re finishing it off with a commit-range that contains a relative date. We’re asking git for a commit 2 months in the past with @{2 months ago}
.
So, what changed in general?
I’m still in a stage where i want a very broad overview, so i’ll ask git to tell me which files changed. Again, here’s the command first, and then an explanation:
$ git diff --stat -w origin/topic/2015-motoren@{2 months ago}..origin/topic/2015-motoren -- . ":!config" ":!vendor" .gitignore | 6 ++ Gemfile.lock | 37 +++------- README.md | 0 ... 42 files changed, 260 insertions(+), 313 deletions(-)
--stat
is one of my favourite modifiers. It works on git log
, too! It will print this list of filenames with the +/- summary. -w
ignores whitespace changes. I’m not interested in those, they may well be the result of a badly configured editor or a refactoring. Usually that’s not what I’m looking for. Then we specify a range of commits again.
Some areas may not interest you at all. We have a project setup where a set of generated files get checked in (we have a good reason for it!), and they change frequently but are of no consequence. I’ll ignore those paths, too. This is done by telling git that only paths follow with two dashes: --
. After that we need a base, which is .
and then we can exclude all the things that clutter up the output. Here, it’s config and vendor. So i’ll add ":!config" ":!vendor"
at the end. :!
in front of a path means “exclude this”.
A quick glance at specific files
At this point, maybe you want quick confirmation that certain configuration items are as expected. You could checkout
a branch, or you could just look at the file directly! In our example, we’re looking at a Gemfile, which lists all the dependencies of a project.
$ git show origin/topic/2015-motoren:Gemfile source 'https://rubygems.org' gem 'rake' # and so on
We’re telling git show to pull up a file Gemfile
, referenced by a ref origin/topic/2015-motoren
. This is separated by a colon. The command is very fast, and you don’t need to change your current working tree!
Ready to pull!
There’s an almost infinite amount of possibilities in gits commands. It’s sometimes hard to tell from the manual, what a real-world application might be. I encourage everyone to curate a list of their favourite combinations. If you have another question or a simpler answer, please share them in the comments!