Table of Contents
git show command cheatsheet
git-show is a command to view objects such as blobs, trees, commits, and tags. You can check an object's details by specifying the SHA1.
git show <SHA1>
Use the pretty option to control the length of viewable metadata.
git show --pretty=<decoration>
The decoration can be oneline, short, medium, full, fuller, raw, or a formatted string.
OR
abbreviate the SHA1 or not.
git show --abbrev-commit git show --no-abbrev-commit
It would be best to understand git objects before seeing practical examples of the above commands.
For that reason, we will explain git objects, creating them from scratch. We will then manipulate them using the git-show command. What is more? Let's dive into section two of this tutorial.
Understand git objects before applying git-show
Think of git as an API for version control. You can interact with the API through two routes: plumbing and porcelain commands.
You mostly interact with the high-level (porcelain) commands such as git init, stage, and commit. That is fine. But if you want to deeply understand what happens in the background, you should use low-level (plumbing) commands as follows.
Initialize a repository
A repository is a collection of commits. Commit objects reference trees. Tree objects, in turn, reference blobs and other trees. Finally, blobs contain file objects.
Git, collectively, refers to the three primary object types as objects. To interact with the objects, we need a naming system. So, instead of cramming the 40 characters in the SHA1, we use an easy-to-remember name. The naming system is called refs.
The objects and refs are directories created inside the .git subdirectory on initializing a repo. Git tells us it cannot recognize a repository before we initialize it.
git status
Instead of running git init, let's create the folders manually.
mkdir .git mkdir .git/objects mkdir .git/refs
For git to track the versions of files, it must be aware of the pointer to the latest commit: HEAD. The HEAD is a file in the .git
subdirectory, referencing the latest branch tip.
A branch is a named reference to a commit. Since a branch is part of the object naming system, git stores it in the objects directory we created above. However, instead of calling the named references branches, git refers to them as heads.
Let's create the directory.
mkdir .git/refs/heads
And fool git that the latest commit lies in the main branch. Although we have not created the main branch, git trusts us.
echo "ref: refs/heads/main" > .git/HEAD
At this point, git considers our directory a repository: it has the HEAD file and objects and refs (with data about the latest branch) directories.
Let's list the files and their contents.
ls .git cat .git/HEAD ls .git/refs ls .git/refs/heads
And recheck the status.
git status
The API is intelligent enough to realize that we are on the main branch and have not made any commits yet. Let's move to the next step in the git-show tutorial: staging changes from scratch.
Stage changes
Staging changes entails creating a blob, updating the index, and creating a tree object.
Create a blob
Before creating a blob, the objects' directory is empty. Running the ls command on the .git directory
ls .git/objects
returns nothing.
Let us create a blob and reinspect the directory.
echo "first content" | git hash-object --stdin -w
Here, we are creating a blob of SHA1 using the hash-object method. We tie the string, first content, to the blob using the standard input option, --stdin
, and a write operation, -w
, to the database.
We get a lengthy output. Mark its first two characters and recheck the objects directory.
ls .git/objects ls .git/objects/66
The objects directory has a subdirectory beginning with two characters of the blob object. Inside the subdirectory are the remaining parts of the SHA1. Git partitions SHA1 objects that way to ease their search.
How do you know the SHA1 is a blob? You can view the object type, content, or size using the cat-file
command.
How to view blob objects without the git-show command
Type
Supply the -t
option in the cat-file
command.
git cat-file -t <SHA1> git cat-file -t 66bc72995f76e56c0b92a7371cb3de2c9b3b8558
Content
Replace the -t
with -p
option in the cat-file
command.
git cat-file -p <SHA1> git cat-file -p 66bc72995f76e56c0b92a7371cb3de2c9b3b8558
OR
List all objects with their types and sizes.
git cat-file --batch-check --batch-all-objects
OR
Print the full path to the object.
find .git/objects -type f
Update the index
The update-index
command
git update-index --add --cacheinfo 100644 66bc72995f76e56c0b92a7371cb3de2c9b3b8558 file1.txt
helps in caching the blob details.
We are updating the database with a blob id 66bc72995f76e56c0b92a7371cb3de2c9b3b8558, containing the contents of a new file, file1.txt
. We do that by caching a 16-bit file mode of value 100644
. A value of 100644 in the git database means we handle a normal file; 100755
, executable, while 120000
is a symbolic link.
We have created the blob and new file at the index. The problem is that git cannot account for the new file in the working directory. It thinks we have deleted an old file and staged a new one on caching the blob with the new file.
git status
We can correct the confusion by inserting the blob's content into the new file.
git cat-file -p 66bc72995f76e56c0b92a7371cb3de2c9b3b8558 > file1.txt
Then recheck the status and confirm the new file's content.
git status cat file.txt
Create a tree
Let's create a tree from the blob.
git write-tree 66bc72995f76e56c0b92a7371cb3de2c9b3b8558
We get a new object. Let's git-show its type and content.
git cat-file -t b4032b5f2e25e7c55cadd69b5980cceab3cde275 git cat-file -p b4032b5f2e25e7c55cadd69b5980cceab3cde275
The batch option and the find command confirm we have two objects: a blob and a tree.
git cat-file --batch-check --batch-all-objects find .git/objects -type f
Git commit
We can create a commit object from the tree using the plumbing command: git commit-tree.
Check the status, make a commit and recheck the status.
git status git commit-tree b4032b5f2e25e7c55cadd69b5980cceab3cde275 -m "Initial commit" git status
We have a new (commit) SHA1 of 34f94cac89e029f8d83d0a17dea58b6becaeb8ef, but the index and history did not get updated. Here is the reason.
We created a commit object without updating the current branch. So, git goes to check the HEAD file and finds that the latest commit lies in refs/heads/main
. But the main branch does not exist yet.
Let's create the branch and reference the latest commit using the update-ref
plumbing command.
git update-ref refs/heads/main 34f94cac89e029f8d83d0a17dea58b6becaeb8ef
The echo command
echo 34f94cac89e029f8d83d0a17dea58b6becaeb8ef > .git/refs/heads/main
would achieve similar results to the update-ref command.
Recheck the status and history.
git status git log
The index and history got updated.
Now that you have a deep understanding of git objects and how to manipulate them using plumbing commands, let us git-show the objects using porcelain commands.
Lab setup to git-show objects using the git show command
I am copying the URL to the git_tags_lesson
repository on GitHub.
Clone it on my terminal. And cd into it.
We can create, stage, and commit a file using the high-level porcelain commands: git stage and git commit. But there is no need for that because the cloned repo has objects and refs to practice the git-show command.
The refs include heads (branches) and tags. Like a branch, a tag tells more about a commit.
Example~1: git-show objects
List the objects.
git cat-file --batch-check --batch-all-objects
And check the details of the latest commit, blob, tag and tree.
git show 02bed804eaf26951a769491df9227e6756727aa9 git show 28fab796c76056ab246eaa479428c8aedcc9e836 git show 31a202f5ee4fa45a4487010e5cd509d2fe6ee925
We can also view tag details by specifying its name instead of the SHA1.
git show v1.3
Example~2: git-show desired lines in a commit
You can git-show a commit object's output by controlling portions to view. For instance, the oneline decoration
git show --pretty=oneline
shows only the diffs data, ignoring the author and timestamp information. The full option
git show --pretty=full
shows the author information, commit message, and diffs of the latest commit.
We can also use the --abbrev-commit
options to control git-show latest commit SHA1 output characters. The --abbrev-commit
reveals seven characters
git show --abbrev-commit
Whereas the --no-abbrev-commit
option shows the forty characters.
git show --no-abbrev-commit
Key Takeaway
The git-show command is crucial in exploring the contents of a git object. However, failure to understand git objects can prevent you from exploiting the full potential of the command.
Now that you have a deep understanding of git and git objects, go ahead and manipulate the objects using plumbing and porcelain git commands, as illustrated in this tutorial.