What is the reason for the /a /b prefixes of git diff

I've been using Git for some years now and always wondered why git diff prefixes the names of modified files with a/ and b/. I expected to eventually stumble upon a use-case where it is useful, but until now it was always annoying and never helpful.

What is it good for? Why is this enabled by default? In which situations is it useful?


Solution 1:

As mentioned in the diff man page, a/ and b/ represent the prefix to differentiate source and destination.

Actually, you have the options:

--no-prefix

Do not show any source or destination prefix.

--src-prefix=<prefix>

Show the given source prefix instead of "a/".

--dst-prefix=<prefix>

Show the given destination prefix instead of "b/"

Solution 2:

If you don't find it useful, you can turn it off with:

git config --global diff.noprefix true

Solution 3:

These directory prefixes are there basically for compatibility and chosen as a sensible defaults. Explanation follows.

Before git

Before git (and other VCS), the workflow to create a patch for multiple files could have been, for example, the following:

  • Let's say you have a source code of a project asdf in a directory asdf-source.latest.
  • You copy the directory to a new directory (e.g. asdf-source.new, ideally hard-linking the files inside).
  • Now you can make all your changes in asdf-source.new, try to compile the code, test it, etc.
  • After you're done, you create a patch using e.g. diff -r asdf-source.latest asdf-source.new >new_feature.patch. The output evolved in time as well. Apart from other things, git uses an "unified" output by default, which might be acquired using diff's -u parameter.

Now you can see the patch has paths to changed files using the directory names.

The person (or build script, and so on) applying your patch will then use patch instead of using git apply or git am. In order for the command to find proper files, the directory name must be removed from the path, using patch's -pN option (N shows the number of directory names and separators to remove). In the above case, the command used could be patch -p1 <new_feature.patch. This makes it possible for the patch creator to use his/her own directory names.

If you ever encounter a script patching some project using a lot of patches (usually used for back-ported patches for stable package versions in Linux distributions for example), the patches may vary in the format. The patch command is able to detect those formats properly, but it is a little bit harder with the paths (how many directories to remove). Some problems with that:

  • Forcing developers to use 0 directories is not very nice.
  • Having patch look for the file might be dangerous (as it may find a different file).

So having everyone sending patches that can be applied with patch -p1 seems the most sensible way to take.

Back to git

When git was created, it adopted sensible defaults (which are compatible with most project's submission guidelines, mainly kernel) for such options. Thanks to this you are able to use git and send a properly formatted patch to someone who uses patch to apply it and vice versa (git is able to handle diff-created patches as well). Having "a" and "b" as prefixes in particular saves space (and a tiny percentage of bandwidth) while keeping everything working.

You can set git config diff.mnemonicprefix true in order for git to use different prefixes depending on what you are comparing (see git help config for further details).

Solution 4:

If you want to add git diff --no-prefix to your .gitconfig manually, just add the following:

[diff]
noprefix = true

Solution 5:

It is to differentiate source and destination. You can also change it to be more meaningful:

--src-prefix=<prefix>

Show the given source prefix instead of "a/".

--dst-prefix=<prefix>

Show the given destination prefix instead of "b/".

http://git-scm.com/docs/git-diff