分享

How to Create and Apply Patches in GIT using diff and apply Command

 WUCANADA 2015-05-19

How to Create and Apply Patches in GIT using diff and apply Command

by on March 24, 2014

Git LogoCreating a patch in GIT is a great way to share changes that you are not yet ready to push to a public branch of a project.

To better understand how we will create a patch, lets first discuss a little about how GIT stores changes.

If you are new to GIT, install git and get a jumpstart from this GIT introduction article.

The first time a file is committed to a project in GIT, a copy is stored. For all commits after that, GIT essentially stores instructions telling it how to transform the previous version of the project to the newly committed version.

In GIT, these instructions are called “diffs” . Whenever you checkout a branch, GIT will basically start at the original state of the project, and apply all of these diffs in order, to to get to the desired state.

Knowing now how GIT stores commits, it is easy to see that a patch file will simply be a concatenation of the diffs for each of the commits that the patch will span.

For our example, lets assume the following situation: We have a simple project with 2 branches: master and experimental.

$ git log --oneline --all
  * b36f227 (experimental) third commit -- added file3
  * f39ebe8 second commit -- added file2
  * 04a26e5 (HEAD, master) first commit -- committed file1

Master is currently at the first commit, while experimental is 2 commits ahead of it. In each commit, I added a file named file1, file2, and file3 respectively. Here is the current state of each branch:

On master, we only have file1:

$ git status
On branch master
nothing to commit, working directory clean

$ ls
file1

While on experimental, we have all 3 files:

$ git status
On branch experimental
nothing to commit, working directory clean

$ ls
file1 file2 file3

In this tutorial, we’ll explain how to create a patch of the changes on the experimental branch and apply them to the master.

Creating the GIT Patch

We will use the git diff command to create the diff output, then redirect it into a file. The form of the diff command we will use is as follows:

git diff from-commit to-commit > output-file

where:

  • from-commit – the point at which we want the patch to start. (In our case, the point at which experimental diverges from master)
  • to-commit – the patch will span the changes up to and including this point. (In our case, the most recent commit of experimental)
  • output-file – the patch will be written here

Note: if either from-commit or to-commit are omitted, they will be assumed to be HEAD

We specify the two commits by their unique hash. Generally, you only have to specify enough of the commit hash to ensure its uniqueness (4 characters will probably do it).

$ git diff 04a2 b36f > patch.diff

$ ls
patch.diff file1      file2      file3

As you see from the above output, the patch file has been created.

In this special case, where we want to create a patch of the entire branch, we can let GIT do some of the work for us. We can let GIT determine the point at which our experimental branch diverged from the master branch using the git merge-base command:

git diff $(git merge-base <public branch> <experimental branch>) > <output file>

git merge-base will determine the most recent common commit between 2 branches. Notice also how this time we have omitted . It will be defaulted to HEAD, and since the experimental branch checked out, HEAD will be the most recent commit of the experimental branch.

$ git diff $(git merge-base master experimental) > anotherPatch.diff

$ ls
anotherPatch.diff patch.diff  file1  file2  file3

Again, the patch file has been created. These patch files are identical.

Applying the GIT Patch

Once the patch file has been made, applying it is easy. Make sure that the branch you have checked out is the one that you want to apply the patch to (master in our case). Then you can apply the patch using the git apply command: git apply

$ git status
On branch master
... (rest of output omitted) ...

$ ls
anotherPatch.diff patch.diff  file1

$ git apply patch.diff

$ ls
anotherPatch.diff patch.diff  file1  file2  file3

The changes from the experimental branch have now been replicated on master.

Warning: Although applying a patch in this way will exactly replicate content, no commit history will be replicated. This means that even if the patch you create spans several commits, it will appear as a single set of changes when applied. You will lose both the knowledge of how the commits were broken up and also the messages for each commit. Lets compare the commit history for both branches:

On experimental, we had 3 commits, each with a meaningful commit message.

$ git branch
  * experimental
    master
$ git log --oneline
  b36f227 third commit -- added file3
  f39ebe8 second commit -- added file2
  04a26e5 first commit -- committed file1

However, our patch simply applied the actual changes to the master branch.

$ git branch
  experimental
  * master
$ git log --oneline
  04a26e5 first commit -- committed file1

Applying the patch did not commit the changes, nor did it bring any of the commit history associated with these changes with it. Be cautious of this when using patches in GIT.

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多