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?
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.
If you don't find it useful, you can turn it off with:
git config --global diff.noprefix true
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 directoryasdf-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).
If you want to add git diff --no-prefix
to your .gitconfig manually, just add the following:
[diff]
noprefix = true
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
精彩评论