Convince git blame that one branch is more relevant to history than another

253 views Asked by At

I like to use git blame as a secondary form of documentation. It's really useful to check why a commit was made, and when and by whom.

But sometimes the history of a particular line gets lost. Some situations where this might happen:

  • A change is made, but then reverted.

  • Someone re-indents the file and commits it. Later the standard indentation is restored and committed.

  • Someone copies the files into a new branch/repo with no history. I still have the original history in a branch, I want to merge it into the new branch.

In all these cases git blame will show the latest changes to the file, which is usually not very useful. E.g. "Restore indentation" or "Revert commit #123" or "Initial commit: all the files".

Is there any way to hint to git blame that we are more interested in the older history than the new one?

Here is the situation:

... - A - B - C
  • Commit A has good annotations for all the lines in the file.
  • Commit B reindented the entire file.
  • Commit C (possibly a revert) restores the file to how it was in commit A.

I was wondering if we could perform a magical git merge with a priority parent:

        .-------.
       /         \
... - A - B - C - D
  • Commit D tells git that A is the priority history for git blame to follow.

Another possibility that I would find acceptable:

            E - F 
                 \
... - A - B - C - D
  • Commit E is a new empty branch.
  • Commit F adds only the file of concern.
  • Commit D merges the two histories, making F the priority for history.

I am hoping to make this permanently part of history. I am not really interested in passing extra options to git blame when searching the history.

1

There are 1 answers

0
LightBender On BEST ANSWER

Both of your scenarios could theoretically be created, but neither would produce the output you desire, as the "change" would still be detected as part of commit C. And both would require substantial amounts of manual work to get there. (I'd have to test what happens in a baseless merge, but the second scenario might actually delete all the other files in your repo with the merge.)

Remember that git stores snapshots of the code and things like filenames, folders, lines, commit messages, etc. are more like metadata to describe the content inside git's brain.

Git blame by its nature only cares about the content of the current blob and where that code originated. It would not see a change between the merged branch and the code and keep looking for a commit that was different to report.

If you really want to eliminate the whitespace changes so vanilla blame will give you the output you want, your best option would be an interactive rebase where you squash those commits together under the initial commit's message and author, but that of course assumes you haven't pushed the code to a remote and again this requires manual intervention.

I know you said you didn't want to pass extra options to blame, but the easiest and most consistent options would be to pass the -w flag and blame will do more or less what your use case describes, and tell you the commit of the last substantive (non-whitespace) change to the line.