Git and libgit2
Mike Slinn

Low-Level Git Commands

Published 2023-03-13. Last modified 2023-05-15.
Time to read: 4 minutes.

This page is part of the git collection.

This article discusses low-level git commands. It builds on the material presented in Git Concepts. The commands are presented in alphabetical order.

Unfortunately, I do not say much of interest in this page between git-cat-file (next), and git-rev-parse. This page will be updated.

The version of git used in this article is:

Shell
$ git --version
git version 2.37.2 

Git-Cat-File

Here is the help information for git-cat-file.

Shell
$ 

Obtain Reference Type

This example obtains the type of a reference for .gitignore at HEAD:

Shell
$ exec git cat-file -t HEAD:.gitignore
blob 

Remember, a git blob is just a stored file, and a git tree is just a stored directory.

Display File From SHA

Two syntaxes are possible to display the contents of a file, given its SHA:

Shell
$ git cat-file -p a997766
Shell
$ git cat-file a997766^{blob}

Display File by Commit and Name

This example lists the first 10 lines of the contents of the version of the .gitignore file at the HEAD commit:

Shell
$ echo HEAD:.gitignore | git cat-file --batch | head
6e11c49ab69e6d2ca5109dffd269b0ce3e97f767 blob 583
.yarn/*
!.yarn/cache
!.yarn/patches
!.yarn/plugins
!.yarn/releases
!.yarn/sdks
!.yarn/versions
.bsp/
exe/ 

Git-Commit-Tree

Shell
$ 

Git-Describe

The help information is:

Shell

Here is an example:

Shell
$ cd="$jekyll_pre" git describe HEAD~3
v1.3.0-4-g3325b45 

Git-Diff

Git-Diff can create patches between two refs. Here is the help message:

Shell
$ 

To create a patch between HEAD and the previous commit:

Shell
$ 

Git-Hash-Object

Computes the object id (oid) for an object, and optionally store it as a blog.

Shell
$ 
hash-object from stdin
$ echo 'test content' | git hash-object --stdin
d670460b4b4aece5915caf5c68d12f560a9fe3e4 

Git-Log

Git log is flexible and powerful. Here is the help message

Shell
$ 

View the N Most Recent Commits

The following uses git-log to view the commit message, the commit date, the branch, the remote branch and author information of the most recent commit on the current branch:

Shell
$ git log -1
commit d9eaf1372978872c232c2875c7376f4e9e2dbd7f
Author: Mike Slinn <mslinn@mslinn.com>
Date:   Mon May 15 14:29:46 2023 -0400
this is a comment

Similarly, git log -N returns information about the N most recent commits.

Shell
$ git log -3
commit 795e7d363e0677ebf64ff02fc8e2e03bccf1ff9f (HEAD -> master, origin/master, origin/HEAD)
Author: Mike Slinn 
Date:   Thu Jul 13 14:20:50 2023 -0400
this is a comment
commit c0b0e51264c6077815241c8d0c584f2746cd30ab Author: Mike Slinn Date: Thu Jul 13 14:03:44 2023 -0400
yet another comment
commit a34f1b489ae450edec45acfedd46177135ae4bd6 Author: Mike Slinn Date: Thu Jul 13 14:02:54 2023 -0400
yay, another comment

Find Commit Of the First Version of a File

To get information about the first commit that has a specific file in it:

Shell
$ git log --diff-filter=A -- README.md
commit c8c92b5f19e49402aa367d470fb89b289ae788f0
Author: Mike Slinn 
Date:   Sat Jul 11 21:11:38 2020 -0400
This is the comment

To specify a file path, do not provide a leading slash. For example, write the path this way:

Good example of a path, without a leading slash
$ git log --diff-filter=A -- path/to/file.ext

Do not write it this way:

Bad example, path has a leading slash
$ git log --diff-filter=A -- /path/to/file.ext

Obtain Commit SHA Containing the First Version of a File

To get the hash of the first commit that has the file in it:

Shell
$ git log --format="%h" --diff-filter=A -- path/to/file.ext
c8c92b5 

To get 9 digits of the hash, use the --abbrev option:

Shell
$ git log --format="%h" --abbrev=9 --diff-filter=A -- path/to/file.ext
c8c92b5f1 

Git-Ls-Files

Here is the help information for git-ls-files.

Shell
$ 

Git-Ls-Tree

Git ls-tree shows the contents of a tree object. This is the git-ls-tree man page:

Shell
$ 
  • -t seems to be the default
  • --abbrev=6 shortens the SHAs to the first 6 characters, which is usually enough to make them unique

HEAD points to the snapshot of the most recent commit to a branch. To see what the first 10 lines of that snapshot looks like, run the following in the root directory of your repository:

Shell
$ git ls-tree --name-only HEAD | head
.bundle
.gitignore
.rubocop.yml
.ruby-version
.shellcheckrc
.vscode
404.html
670nm.html 

Directory enties can be suppressed, such that only files are recursively displayed, via the -r option:

Shell
$ git ls-tree --name-only -r HEAD | head
100644 .bundle/config
.gitignore
.rubocop.yml
.ruby-version
.shellcheckrc
.vscode/launch.json
.vscode/settings.json
.vscode/tasks.json
404.html
670nm.html 

The default is to display the commit’s mode, type and SHA as well as the file name:

Shell
$ git ls-tree HEAD | head
040000 tree aaf10b00a2daba90550321ed46912db00c690a62    .bundle
100644 blob 6e11c49ab69e6d2ca5109dffd269b0ce3e97f767    .gitignore
100644 blob f480670f694bc102098c514b695b177b6258cc3f    .rubocop.yml
100644 blob fd2a01863fdd3035fac5918c59666363544bfe23    .ruby-version
100644 blob 4e0ef479723860d16a332347a691d422a0ef2770    .shellcheckrc
040000 tree bd6408dfd6ecaba73a77c4cff0c9a82dadff76d6    .vscode
100644 blob 14ad2b4cc7658f00f26da39cc70583f6750c2943    404.html
100644 blob 1fe1aa295d166663285b54cb94954bfe19da152c    670nm.html
100644 blob 02862b254846b5669596de4d2795d023ebc87c7c    BingSiteAuth.xml
100644 blob e527be14f8b957cbbd3517a16198a701e38f5dd7    Gemfile 

Git-Rev-Parse

This is the help message for git-rev-parse – the Swiss Army Knife for git. It supports revision syntax.

Shell
$ 

There are several ways to discover the SHA of the HEAD commit:

Shell
$ git rev-parse HEAD
d9eaf1372978872c232c2875c7376f4e9e2dbd7f 
$ $ git rev-parse --symbolic-full-name HEAD refs/heads/master
$ git rev-parse refs/heads/master d9eaf1372978872c232c2875c7376f4e9e2dbd7f
$ git rev-parse --short HEAD d9eaf137
$ git rev-parse --short master d9eaf137
$ git rev-parse --short refs/heads/master d9eaf137
$ git rev-parse --short @ d9eaf137

Read about accessing parent commits. You can get the SHA of the penultimate commit (the parent of HEAD), and the SHA of the commit before that:

Shell
$ git rev-parse --short HEAD~
e4e53f69 
$ git rev-parse --short HEAD~2 1d711f74

Use the reflog to access the snapshot of the previous value of HEAD:

Shell
$ git rev-parse --short HEAD@{1}
e4e53f69 

Git-Show

This is the help message for git-show:

Shell
$ 

Git-Show-Ref

This is the help message for git-show-ref:

Shell
$ 

View all refs that are a HEAD in a repo:

Shell
$ git show-ref --abbrev=8 --head
d9eaf137 HEAD
d9eaf137 refs/heads/master
d9eaf137 refs/remotes/origin/HEAD
d9eaf137 refs/remotes/origin/master
e57fd0ba refs/stash
c05d0d37 refs/tags/1 

Show all references called master, including tags, heads and any other refs, including remote refs:

Shell
$ git show-ref --abbrev=8 --head master
d9eaf137 HEAD
d9eaf137 refs/heads/master
d9eaf137 refs/remotes/origin/master 

Show the SHA for HEAD:

Shell
$ git show-ref -s --head HEAD
d9eaf1372978872c232c2875c7376f4e9e2dbd7f
d9eaf1372978872c232c2875c7376f4e9e2dbd7f 

Git-Symbolic-Ref

The help message is:

Shell

Obtain the value of your HEAD:

Shell
$ git symbolic-ref HEAD
refs/heads/master 

Set the value of HEAD to the test branch. (This is what git branch test does).

Shell
$ git symbolic-ref HEAD refs/heads/test
$ cat .git/HEAD ref: refs/heads/test

Git-Update-Index

This is the help message:

Shell
$ 

Git-update-index is a huge command. Here are two use cases:

Adding File

Similar to git add, git update-index --add adds a file in the working tree to the index. Call git write-tree to write the objects to the git database. Note that this does not make a commit. Here are the steps to make a commit using low-level git commands:

Shell
$ git update-index --add new.txt
$ SHA1="$( git write-tree }"
$ echo 'First commit' | git commit-tree $SHA1

Hiding Changes to Files and Directories from Git

If you need to make a temporary change to a file, and you do not want to commit the change, git update-index has a handy option: --assume-unchanged. This option causes git to temporarily ignore changes to that tracked file or directory. Git considers the changes to the files and directories you specify to be hidden, even though the file system does not consider the file to be hidden. Use it like this:

Shell
$ git update-index --assume-unchanged path/to/file.txt

Next time you run git status you will see that git is no longer aware of the edit. Any future changes to those files or directories will be ignored (hidden).

Shell
$ git commit -am "This is a comment"
$ git push

Actually, git has not forgotten about the file, it is merely ignoring changes to the hidden file. The -v option of the git-ls-files command causes the output to indicate hidden files with the h flag:

Shell
$ git ls-files -v
h path/to/file.txt 

To restore the file’s changes to being noticed by git again, use the --no-assume-unchanged option:

Shell
$ git update-index --no-assume-unchanged path/to/file.txt

You can read more about this option here.

Git-Update-Ref

The help message is:

Shell

The following creates a new branch called my_branch at the current HEAD. This will create a file called .git/refs/heads/my_branch.

Shell
$ git update-ref refs/heads/my_branch HEAD

The above is equivalent to:

Shell
$ git branch my_branch

Git-Write-Tree

This is the help message:

Shell
$ 


* indicates a required field.

Please select the following to receive Mike Slinn’s newsletter:

You can unsubscribe at any time by clicking the link in the footer of emails.

Mike Slinn uses Mailchimp as his marketing platform. By clicking below to subscribe, you acknowledge that your information will be transferred to Mailchimp for processing. Learn more about Mailchimp’s privacy practices.