m33lky
m33lky

Reputation: 7275

searching commit messages in the whole git repo

I'd like to understand the difference between git log --all --grep=<> and git log --grep=<>. My goal is to traverse the whole repo when searching. If I don't add --all, does it mean that I will miss all the commit messages in branches? Looks like a non-intuitive default to me.

Upvotes: 2

Views: 266

Answers (2)

Schwern
Schwern

Reputation: 164809

git log is a tool for traversing the commit graph and printing out commit information. --grep is a filter on this traverse.


git log starts from your current commit (ie. HEAD) and works its way back through history from there.

git log --all visits all commits. This is pretty rare, occasionally needed by an integrator.

--grep is a filter. It filters the stream of commits visited by git log. Filters only remove entries, never add. For each commit git log visits --grep decides whether that should be included. It might make more sense if you think of it like a normal Unix pipe.

git log | grep foo

Defaults should work best with the most common case. Commands like diff and log are most used in development. Integration happens far more rarely. So the defaults are targeted at developers.

The common use of git log for developers is looking for changes which contributed to this commit. They're looking for answers to the question "why is this written like this?" or "where did this bug come from?". That's why the default is to walk the graph from your current commit. It's rare that you want to search commits which haven't been merged into your code, that's more the task of an integration manager.

--grep doesn't change what commits git log visits. If it implied --all, that would be surprising and inflexible. Surprising because it would muddle the meaning of "filter" and it's pretty rare you want to search unrelated branches. Inflexible because how do you search only certain commits? I suppose you could require a --no-all to turn it off, and then maybe more switches, probably --branches, to get what you mean.

There are rare instances where having multiple default behaviors works out, but it's usually a nightmare. It's better to have a firm common use case in mind (development) and not guess about rarer cases (integration). Let rare cases be explicit about what they want.

Upvotes: 1

torek
torek

Reputation: 488183

You're correct that you need --all here (or perhaps you might want --branches instead).

"Intuitive" in git is a bit tricky, and the behavior of git log is intuitive to me, but only because I've studied git and its peculiar notions of how to work with commit graphs.

The log command is not very different from all the other commit-graph-traversing commands. They all work like—in fact, many of then simply run, or run and then use the output of—git rev-list. You give it some starting point commit IDs, or some names or any of the syntax described in gitrevisions, and it finds the SHA-1 IDs of every commit reachable from those IDs.

Every commit inside the repo—including commits that have been "abandoned" (but are still findable via reflogs) because of a rebase copy operation, commits that are on the stash stack, and even git notes commits—works this way, so it would be bad for git log to find all commits. Even the --all flag doesn't actually find all commits.

If you peruse the git rev-list documentation, you'll see that --all means "every reference in the refs/ namespace" (hence all branches, all tags, and notes, but not special references like ORIG_HEAD left behind after a rebase, nor any reflog entries, for instance). The same wording appears in the git log documentation, but I like to refer people to git rev-list since I think it is ultimately more revealing.

Upvotes: 1

Related Questions