Some open source git repos host really useful code but are sometimes not maintained.
If you use that code on a regular basis, you may need to fork it, improve it, and use your enhanced version of that code.
Then someday the original repo is updated, a brand new version of the code you forked is released, and either you will lose all your changes or you will miss the new features.
To get the best of the two versions, you need to merge them.
There are many solutions and any that fits your needs is valid.
My problem was to merge up to 50 commits and I hate having to fix so many conflicts; it can take days. I also knew there was code that would need refactoring, so my idea was to avoid merging the whole changes in one batch. In this paradigm the am
command is my best git option.
What is git am
?
git am
is a super useful command which can be used for many things as it’s reading and parsing the mailbox containing the commits you specify and allows you to use only parts of the extracted data such as the code diff, the autor, the message…
In this case, I used it to cherry pick a commit from a repo and add it to another, but this command is way more powerful than this.
You can find the whole documentation here https://git-scm.com/docs/git-am
knowledge required
UNIX shell basic usage
How do we use it?
For this use case, you need to have the two repos locally.
Let’s say we have this architecture:
$ demo ls
my-forked-repo the-last-version-repo
Go to last version repo
$ cd the-last-version-repo/
Use the following line for each commit you want to import in the new version
$ git --git-dir=../<My-forked-repo>/.git \
format-patch -k -1 --stdout <your commit SHA> | \
git am -3 -k
Here is the full explanation of the command: https://stackoverflow.com/a/9507417
If there’s no conflicts, console will just display
$ Applying <your commit message>
And if you type in your console:
$ git status
You will see that you have a commit ahead of HEAD.
I’ve got a conflict
If for some reason the commit cannot be merged automatically, console will display a message with the conflicting files list and a small explanation of the failure. In this case, you can get more information with:
$ git am --show-current-patch
I want to solve it
To resolve the conflicts, go to the files, manually keep the code you want then go to your console and add them to git:
$ git add <path/to/file>
After adding the files to git, you will be able to do:
$ git am --continue
which will commit the files for you. A $ git status
will produce the same result as before.
I do not want to solve it
In the case you want to handle the conflict without git, you can just
$ git am --abort
Which will abort all the commits you’re trying to import. Or you can use:
$ git am --skip
which will abort the import of the current commit having a conflict. In both cases, the files will be left as they were before you typed the command.
Notice that you can’t use these commands to resolve a conflict triggered by another git command (e.g git merge
…)
I imported my commit, so what now?
Basically, nothing, you’re all good to go, push the commits to your branch whenever you want with
$ git push <your remote name> <your branch name>
And that’s it. If for some reason you need to update the message of the commit, use
$ git commit --amend
Careful, it only works with the last commit. There are ways to do the same with an older commit, but it involves rewriting the tree and this will change the commit SHA as well, read the git documentation for more details.
If you made a lot of changes on a commit that wasn’t originally yours, it may be accurate to change the author to yourself, for this use
$ git commit --amend --author="Author Name <email@address.com>"
On your last commit. For olders commit, it’s exactly as above.
Happy merging!