24

The long SHA can be gotten like below:

repo = git.Repo(search_parent_directories=True)
sha = repo.head.object.hexsha

Or, in git 3.1.7:

sha = repo.head.commit.hexsha

How about short one? (short SHA is decided by the scale of the repo, so it should not be like sha[:7])

lemonhead
  • 5,328
  • 1
  • 13
  • 25
Kentaro Wada
  • 505
  • 1
  • 4
  • 13

6 Answers6

21

As far as I can tell, the gitpython Commit object does not support the short sha directly. However, you can use still gitpython's support for calling git directly to retrieve it (as of git 3.1.7):

repo = git.Repo(search_parent_directories=True)
sha = repo.head.commit.hexsha
short_sha = repo.git.rev_parse(sha, short=4)

This is the equivalent of running

git rev-parse --short=4 ...

on the command-line, which is the usual way of getting the short hash. This will return the shortest possible unambiguous hash of length >= 4 (You could pass in a smaller number, but since git's internal min is 4 it will have the same effect).

lemonhead
  • 5,328
  • 1
  • 13
  • 25
  • Thank you. actually, i don't want to use shell command, because it makes script run much more slowly.. maybe fixed length of hash does work in most cases, so i will use it. – Kentaro Wada Aug 12 '15 at 06:33
  • Hmm... do you mean shelling out yourself directly or using the git-command database internal to `gitpython`? Using `repo.git.revparse()` like I suggested does the latter, and should be really fast. If your concern is the memory consumption or spawning new procs, you can instead use `git.Repo(odbt=GitDB)` for a pure-python solution, though it runs 2-5 times slower. – lemonhead Aug 12 '15 at 06:46
  • It seems that `repo.head.object.hexsha` does not call shell command, and this is ideal one. because I'm correcting git status information to display it in shell prompt. (so it should be fast) – Kentaro Wada Aug 12 '15 at 06:48
  • > "Using repo.git.revparse() like I suggested does the latter" really. I didn't know that, thanks. – Kentaro Wada Aug 12 '15 at 06:50
  • Actually, small correction; looks like if you are using python > 2.4, it will default to `gitdb`, which is pure-python, but in any event, using `repo.git` will still run commands via `Popen`. Still internal to gitpython though – lemonhead Aug 12 '15 at 07:03
  • So, without Popen, it is impossible to get shortened hash. I'm using fixed length. thanks. – Kentaro Wada Aug 12 '15 at 07:27
  • This answer should define the `sha` variable like @mu did below in order to be complete – Addison Klinke Apr 02 '20 at 21:31
  • As someone also mentioned there is a way of doing it https://stackoverflow.com/a/63453759/99834 – sorin Aug 17 '20 at 15:17
  • @sorin As per [gitpython 3.17 documentation](https://gitpython.readthedocs.io/en/stable/reference.html#module-git.objects.commit) `commit.hexsha` still returns the full 40 byte hex version rather than the short version -- I think `git.rev_parse()` remains the valid way to do this. I've added how to get at the long sha in the latest gitpython – lemonhead Aug 19 '20 at 08:34
6

You will need to use the short argument of rev-parse here to generate the smallest SHA that can uniquely identify the commit. Basically, the short will call the internal git API and return the shortest possible length string for the SHA which can uniquely identify the commit, even if you've passed a very small value for short. So effectively, you can do something like below, which will give you the shortest SHA always (I use short=1 to emphasize that):

In [1]: import git
In [2]: repo = git.Repo(search_parent_directories=True)
In [3]: sha = repo.head.object.hexsha
In [4]: short_sha = repo.git.rev_parse(sha, short=1)
In [5]: short_sha
Out[5]: u'd5afd'

You can read more about this from the git side here. Also, as mentioned in the man-page for git-rev-parse, --short will by default take 7 as its value, and minimum 4.

--short=number

Instead of outputting the full SHA-1 values of object names try to abbreviate them to a shorter unique name. When no length is specified 7 is used. The minimum length is 4.

Community
  • 1
  • 1
Anshul Goyal
  • 73,278
  • 37
  • 149
  • 186
5

For gitpython 3.1.15, there seems to be a shorter way of getting the hash compared to the other answers.

You can simply do

hash = repo.git.rev_parse(repo.head, short=True)

You do not need explicitly obtain

sha = repo.head.commit.hexsha

first.

Gino Mempin
  • 25,369
  • 29
  • 96
  • 135
Simon Rose
  • 381
  • 5
  • 11
3

actually, you need to use

short_sha = repo.git.rev_parse(sha, short=True)

short=4 always shows 4 letter hash even in my ginormous git base

  • From the [`git-rev-parse` docs](https://git-scm.com/docs/git-rev-parse): "--short[=length] Same as --verify but shortens the object name to a unique prefix with at least length characters. The minimum length is 4, the default is the effective value of the core.abbrev configuration variable (see git-config[1])." Presumably you are getting 4 length hashes because it is still unique in your repo – lemonhead Aug 19 '20 at 08:45
-1

The answers already supplied assume you are calling rev-parse through the shell, which is slow. If you already have a reference to the repo, you can do this by accessing the name_rev property on the Commit object with string truncation as follows. The reference is fixed at the length you supply (here, 8), but it works:

repo.remotes.origin.refs['my/branch/name'].object.name_rev[:8]

The actual output of this command is the full sha, followed by a space, followed by the branch name.

Myer
  • 3,670
  • 2
  • 39
  • 51
  • I don't know what answers you are talking about since literally not a single one calls it through the shell. This solution is also pretty bad because it uses a fixed length of the commit hash which does not have the uniqueness property the rev_parse solution has. – Stefan Fabian Jan 06 '20 at 16:59
  • @StefanFabian the answers that mention `repo.git` end up calling it through the shell under the hood: https://gitpython.readthedocs.io/en/stable/tutorial.html#using-git-directly – Myer Jun 15 '23 at 21:18
  • Ah sorry, you are right! The point that you might need more than 8 characters to preserve uniqueness still stands but I'd like to apologize for the tone. Apart from this, performance-wise this is a great solution. – Stefan Fabian Jun 22 '23 at 20:11
-1

Current answer is outdated and the way to retrie sha of the commit is commit.hexsha.

sorin
  • 161,544
  • 178
  • 535
  • 806
  • This is not a standalone answer to the question of getting a short hash, and is really only relevant as a comment on the outdated answer mentioned. – AnnanFay Sep 17 '20 at 14:02