okaryo.log

Understanding the Basics and Use Cases of git rev-list | okaryo.log

Understanding the Basics and Use Cases of git rev-list

    #Git

Introduction

Recently, I came across the git rev-list command, which I used to retrieve the total number of commits in a repository, as mentioned in the following article:

Fetching All Commit History in a Repository with GitHub Actions

I decided to explore the usage of this command and gather some useful options. Additionally, I considered the practical scenarios where this command could be handy.

Basic Usage

The git rev-list command lists commit objects in reverse chronological order, following the parent commits from the specified branch (or commit).

For example, if you specify the main branch, the output will be as follows:

$ git rev-list main

# Output
ebf897c26a983f936c2c280e5a50e171fa8e1dc0
a4df745d848e0992dd3a208332be48febf997241
0ed481ad7d21138c79a3785737830d5bd8018093

You can also specify a branch or commit. Let’s pass the second commit object from the previous output:

$ git rev-list a4df745d848e0992dd3a208332be48febf997241

# Output
a4df745d848e0992dd3a208332be48febf997241
0ed481ad7d21138c79a3785737830d5bd8018093

By specifying multiple branches or commits, you can perform set-like operations. The following example outputs the set difference between the union of commits reachable from hoge and fuga (excluding the commits reachable from hoga):

git rev-list hoge fuga ^hoga

Additionally, you can use the <commit1>..<commit2> syntax to retrieve the commit objects within that range. From the perspective of set operations mentioned earlier, this is equivalent to ^<commit1> <commit2>, which excludes the common commits reachable from both branches.

Thus, the following two commands produce the same result:

$ git rev-list origin..HEAD
$ git rev-list HEAD ^origin

Additionally, there seems to be a notation using three dots <commit1>...<commit2>. The documentation states that the result is “the symmetric difference between the two operands,” but to be honest, I’m not entirely sure what that means.

It is mentioned that the following two forms are equivalent, so it might mean outputting the difference excluding the merge base. If there are any experts out there, please enlighten us.

$ git rev-list A B --not $(git merge-base --all A B)
$ git rev-list A...B

That covers the basic usage of git rev-list.

Useful Options

Let’s take a quick look at some useful options.

--count

Outputs the number of commits. This option is handy for obtaining the total count.

$ git rev-lsit --count HEAD

-<number>, -n <number>, --max-count=<number>

Limits the number of outputted commit objects. Useful when dealing with a large number of commits.

$ git rev-list -5 HEAD

--since=<date>, --after=<date>

Specifies the date range of commit objects.

$ git rev-list --after='2022-10-10' HEAD
$ git rev-list --after='1 hour ago' HEAD
$ git rev-list --after=1.hour.ago HEAD

--author=<pattern>, --committer=<pattern>

Filters commit objects by author or committer.

$ git rev-list --author=okaryo HEAD

--merges

Outputs only merge commits.

$ git rev-list --merges HEAD

Use Cases

While exploring rev-list, it’s important to consider practical use cases. Let’s explore a few scenarios.

Obtaining the Total Number of Commits

While this can be achieved using rev-list alone, it is still a common use case. It was my first encounter with rev-list, so it’s likely a popular use case.

$ git rev-list --count HEAD

Cherry-picking Multiple Commits

For me personally, the primary use of commit hashes is when cherry-pick. git diff is another scenario where commit hashes may be used. These combined operations can be useful when cherry-pick multiple commits without having to pick them one by one.

# To commit
$ git rev-list --reverse branch1..branch2 | git cherry-pick --stdin

# To only cherry-pick without committing
$ git rev-list --reverse branch1..branch2 | git cherry-pick -n --stdin

Reviewing Recent Changes for a Specific File

Another potential use case for commit hashes is when working with git diff. By combining it with a file path, you can review recent changes for a specific file.

Note: -- is used as an identifier to pass file paths.

$ git diff $(git rev-list -1 HEAD -- package.json)^ -- package.json

These are just a few examples of potential use cases. There are countless other possibilities to explore and discover.

Conclusion

Although I haven’t used rev-list extensively, the statement in the documentation stood out to me:

rev-list is a very essential Git command, since it provides the ability to build and traverse commit ancestry graphs.

This suggests that rev-list possesses powers that I can’t even imagine yet.

Git offers numerous commands, and the Git journey seems to have endless depths to explore.

References


Related Posts

No related posts

Related Posts
Promotion

This site uses Google Analytics.