(n.b. I've accepted Roland's answer, as it is indeed the correct (and simplest) solution starting from git 1.7.4.4, but please consider this question open regarding earlier versions of git down to 1.7.0.4.)
This question is a bit rambling (primarily due to the edits resulting from my subsequent attempts to establish more information on the situation), but the text in the title is the most important bit.
That is: I'm trying to establish the definitive way to ensure that all git commands will display full (un-abbreviated) hashes in their output.
As I am focussed on backwards-compatibility, this needs to cover older versions of git 1.7. Ideally the solutions would work for git 1.7.0.4 (which is used in the still-supported Ubuntu 10.04 LTS), but I'd be happy with a minimum of 1.7.2.5 (for Debian 6 / Squeeze LTS). Anything requiring a version later than 1.7.9.5 (Ubuntu 12.04 LTS) is definitely not ideal, but I'd still love to hear about them.
Please note that I do not wish to lose the ability to have abbreviated hashes -- the purpose behind this question is to ensure that tools interacting with git can always access a complete and unambiguous hash. When I use git manually on the command line I am going to want the normal abbreviations most of the time.
Roland Smith's suggestion of utilising a command-line argument override for
core.abbrev
looked ideal, but sadly only works since v1.7.4.4 (as core.abbrev
did not previously exist). I suspect this means we do need to determine the
most comprehensive set of command-specific arguments (such as git blame -l
)
to produce the equivalent effect.
Some (most?) git commands default to outputting abbreviated hashes. For
instance both git blame
and git-annotate
do this, and this fact was tripping
up the current Emacs support when clashes arose (as they can do prior to git
1.7.11.1 -- see Edit 1 below), as the ambiguous hashes then caused errors when
attempting to act upon them).
Begin Edit 1
I note the following in the Changelog, which suggests that the original problem which prompted this question issue would not arise in more recent versions of git.
Fixes since v1.7.11.1
---------------------
* "git blame" did not try to make sure that the abbreviated commit
object names in its output are unique.
If it's the case that git is supposed to guarantee uniqueness (at least at the time the command is run) for all object names reported by any git command, then that would significantly alleviate my concerns; but obviously a solution to the question which supports earlier versions of git is still going to be of interest.
End Edit 1
That can be fixed with git blame -l
and git annotate -l
, but I don't know
whether these two commands are isolated cases or not, and I want to ensure that
this issue can't arise in other situations.
The only related configurations I can see are core.abbrev
:
Set the length object names are abbreviated to. If unspecified, many commands abbreviate to 7 hexdigits, which may not be enough for abbreviated object names to stay unique for sufficiently long time.
(but I don't want to remove the option of seeing an abbreviated commit), and
log.abbrevCommit
which:
If true, makes git-log(1), git-show(1), and git-whatchanged(1) assume
--abbrev-commit
. You may override this option with--no-abbrev-commit
.
The --no-abbrev-commit
argument isn't a consistent thing, though -- I presume
that only the commands mentioned in that quote recognise it (but see Edit 2
below).
Begin Edit 2
The parse-options API document states:
Boolean long options can be negated (or unset) by prepending
no-
, e.g.--no-abbrev
instead of--abbrev
. Conversely, options that begin withno-
can be negated by removing it.
So the commands which accept --abbrev
(of which there are many) will in fact
all accept --no-abbrev
as well? This negated option is often not mentioned;
although --abbrev=40
would currently be equivalent, of course, even if no
negation was available).
It's not clear to me when the default boolean negation option feature was introduced, however.
In my version 1.7.9.5 git-blame --no-abbrev
results in single-character object
names. In fact it's the same as --abbrev=0
, as blame uses n+1
characters.
Conversely I notice that git branch -v --abbrev=0
gives the full 40
characters.
End Edit 2
A complete list of the potential problem commands with their appropriate options would be excellent, although the ideal solution would be something that would (or at least should) be respected by all git commands (including future commands), but maintains the ability to display abbreviated hashes when desired?
An ugly approach which occurred to me was to create a git config file which
imports the original config file (although I note that importing is only
available from 1.7.10) and then sets core.abbrev
to 40; and to use this via a
temporary GIT_CONFIG
environment variable when invoking git, whenever full
commits are a necessity. I guess this would work, but I'd rather not do it.
Clearly there are/were bugs, and some of the bugs at least have since been fixed; but as the aim is supporting as many (as practical) versions of git that a user might reasonably happen to be running, I'm looking for something which is backwards-compatible.
For what it's worth, here's what I've gleaned from grepping the manual for version 1.7.12.4:
Commands accepting --abbrev
(and thus in theory also --no-abbrev
):
Other options:
Using git -c core.abbrev=40 <command>
is supposed to work on all commands because it "will override whatever is defined in the config files".
It seems to have been introduced in 8b1fa778676ae94f7a6d4113fa90947b548154dd
(landed in version 1.7.2).
Edit2: As phils noticed, the core.abbrev
parameter was added in 1.7.4.4.
Edit: W.r.t. hardcoded hash lengths, you could always look up the hash lengths by looking at the filename lengths in .git/objects/*
when initializing your program/library.
The new updated answer (2021) will be with Git 2.31 (Q1 2021)
The configuration variable 'core.abbrev
' can be set to 'no
' to force no abbreviation regardless of the hash algorithm.
And that will be important when Git will switch from SHA1 to SHA2.
See commit a9ecaa0 (01 Sep 2020) by Eric Wong (ele828
).
(Merged by Junio C Hamano -- gitster
-- in commit 6dbbae1, 15 Jan 2021)
core.abbrev=no
: disables abbreviationsSigned-off-by: Eric Wong
This allows users to write hash-agnostic scripts and configs by disabling abbreviations.
Using "
-c core.abbrev=40
" will be insufficient with SHA-256, and "-c core.abbrev=64
" won't work with SHA-1 repos today.[jc: tweaked implementation, added doc and a test]
git config
now includes in its man page:
If set to "no", no abbreviation is made and the object names are shown in their full length.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With