Collectives™ on Stack Overflow

Find centralized, trusted content and collaborate around the technologies you use most.

Learn more about Collectives

Teams

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Learn more about Teams

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?

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/"

Gringo Suave adds in the comments:

Went with:

git diff --src-prefix="SRC " --dst-prefix="DST " 

to make double-click select and paste work.

@manojlds: Thanks, we were writing practically at the same time anyway. Note: comments.gmane.org/gmane.comp.version-control.git/175850 mentions that the path prefixes of the diff machinery used to by hardwired to "a/" for the source prefix and "b/" for the destination prefix. – VonC Jul 20, 2011 at 16:22 i love how bad the defaults for everything on git are. a and b for origin and destination... how is that clear? anyway, you can also disable for good with git config --global diff.noprefix true – gcb Jul 23, 2015 at 18:54 It would be nice if there was a similar option for the diffs seen when using git add --patch. I love to dbl-click these names for quick pasting into konsole, but it's annoying to always have to trim this stupid, useless prefix. – JFlo Jan 2, 2018 at 22:02

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).

    With git your claim /"Forcing developers to use 0 directories is not very nice"/ makes no sense. There's no a vs b. /"Having patch look for the file might be dangerous (as it may find different file)"/ makes also no sense since there is no old dir a and new dir b. -p0 is the patch default. With -p1 you'll have to type more. So diff.noprefix true is a meaningful default. – rurban Mar 13, 2014 at 12:59 Saying "Forcing developers to use 0 directories", I mean the use case explained in the start of the section. I was easier to have it in 2 directories and the default output would be then applied with -p1. About the "finding a different file", that is of course not that easy, but having -p0 does not strip anything which means that full paths (e.g. /etc/hosts) will be kept and treated as such. This is of course handled in current patch implementation. – nert Mar 25, 2014 at 12:33 @rurban According to the man page of patch(1) version 2.7.1, the default is not -p0. Not using -p (or --strip) option at all will strip all the directory names, so with /u/howard/src/blurfl/blurfl.c "not specifying -p at all just gives you blurfl.c." – nert Mar 25, 2014 at 12:39 You are right. -p0 is required. Sorry. With diff.noprefix true it's also much easier to copy&paste the file. – rurban Mar 26, 2014 at 13:59

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

    [diff]
    noprefix = true
                    This works, but breaks git apply by terms of creating unusable git diffs; see stackoverflow.com/a/57340649 --- git is retarded.
    – Robert
                    Aug 28, 2020 at 17:48
    

    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

    Thanks for contributing an answer to Stack Overflow!

    • Please be sure to answer the question. Provide details and share your research!

    But avoid

    • Asking for help, clarification, or responding to other answers.
    • Making statements based on opinion; back them up with references or personal experience.

    To learn more, see our tips on writing great answers.