Introduction
In the years during which Git evolved, there was no provision of using a central remote repository which different contributors could use to merge their changes to a feature branch or request pull requests. Sending patch file(s) via email was the name of the game. A patch file is a handy way of encapsulating the changes introduced into the repository as part of a commit, into a single file. Patches can be created on a per commit basis or a bunch of commits can be squashed into a single patch file.
Git Format-Patch
The command that is used to create a patch file is format-patch. Various options are available that can be used in conjunction with the command to modify the output as desired. Let’s take a look at the most common operations that use format-patch command.
To learn about the command let’s create a repository and track a text file with some text entries.
$ mkdir PatchFiles
$ cd PatchFiles
$ git init
$ touch file1.txt
$ printf "first line" > file1.txt
$ git add .
$ git commit -m "First commit"
$ printf "\nsecond line" >> file1.txt
$ git commit -am "Second commit"
$ git log --online master
Next let’s create a branch named develop off of the master branch and track a text file with some text entries.
$ git branch develop
$ git checkout develop
$ touch file2.txt
$ printf "first line" > file2.txt
$ git add .
$ git commit -m "First commit in develop branch"
$ printf "\nsecond line" >> file2.txt
$ git commit -am "Second commit in develop branch"
$ git log --oneline
Now that we have laid the groundwork, let’s understand the format-patch command. The format-patch command takes in the name of the branch against which you want to compare the commits of the current branch pointed to by the INDEX pointer. By default, the format-patch creates a patch file for every commit not available in the target branch.
$ git format-patch master
$ dir
In earlier times, when there was no remote repository, such patch files used to be mailed by project contributors to the project maintainer.
Next, we will discuss the two commands that can be used to apply the patch files, i.e., apply and am.
Git Apply
There could be situations that demand the application of changes in a patch to the target branch, but, not include the corresponding commit message into the commit history of the target branch. Git’s apply command is used in such situations.
Apply command helps you to test out the changes introduced by the patch locally before you formally commit them into the repository. Since the changes are applied to the working directory, you can use git diff to view the changes applied. Also, the commit message can be a bit more descriptive signifying the nature of the changes applied.
Let’s see the command in action in code.
$ git checkout master
$ git apply 0001-First-commit-in-develop-branch.patch
$ git status
$ git log --oneline
$ dir
Git AM
Git’s am (Apply Mailbox) command is used in a situation when you are assured of the commits in a patch and want them to be applied verbatim, along with their corresponding metadata consisting of author’s information and commit message.
$ git checkout master
$ git am 0001-First-commit-in-develop-branch.patch
$ git status
$ git log --oneline
$ dir
Word of Caution
If you are selectively applying patches, and if a patch contains an artifact that comes to life in a prior patch, then the application of such a patch will fail. This is because patch files are commit-specific and carry changes specific to the commit.
In such cases, you will be required to sequentially apply patches in chronological order, first bringing the artifact into existence, followed by any changes in the artifact.
$ git checkout master
$ git am 0002-Second-commit-in-develop-branch.patch
We were not able to successfully apply the second patch as the file2.txt came into existence in the first commit, hence first patch. It would be imperative here, to first apply the first patch and then the second patch.
Conclusion
Git provides the ability to create patches as discreet units signifying the evolution of a project and enables the sharing of this evolution in the absence of a central remote repository.
Git offers two ways to apply patches as per requirements.
Git’s apply command applies the changes locally to the working directory and gives you the freedom to further introduce changes in the artifacts before formally committing into the repository.
Git’s am command applies the patches in the repository and includes the commit messages contained in the patches. It retains vital metadata like author information, email, etc..