Separate commits in a single branch to totally new branches - Neuroon Networks

Breaking

Friday, February 7, 2020

Separate commits in a single branch to totally new branches

First of all, let me explain the title of this article. If you are using GitHub you may be faced with a situation like this. Imagine you are implementing a feature for your project. Suddenly you come up with a blocker or an issue that blocks your feature. In order to complete your feature, you have to implement this blocker. And you did implement the feature with the blocker and committed changes to the branch that you are working on. But suddenly you are asked to create a pull request that has the changes for the blocker. So how you are going to separate the changes from the commits. Of course, you can use git cherry-pick but what if one commit has the changes for blocker and the feature. And if you do cherry-pick now you may end up with a mess for sure. Now, this is a real-life scenario that I was faced during my internship period.
In this case, there are some ways to proceed. You can create a new branch from the current branch and remove the unnecessary changes and commit them. But this will give you a long commit history and it would be hard when it comes to reviews. And what I’m gonna show you is the simplest way to overcome this kind of situation. This may be an old approach but it works nicely for me (you know the phrase “old is gold”, yeah that was damn true).
OK let’s do this. First of all, make sure that your master branch is synced with upstream’s master branch. This is necessary in order to create the pull request.
You can simply get the changes from the upstream my typing,

git pull upstream master 
If you haven’t added an upstream use git remote add upstream <repo url.git>

Now take the diff of the master branch and save it to a directory. What you have to do is open a terminal in the root directory (make sure you are in the master branch) and paste the following command with necessary changes.

git archive master | tar -x -C <directory to save the branch status>
You can always use the directory to save the archives one step ahead of the project. 
For example git archive master | tar -x -C ../master-diff.

And now change to the branch that your feature is implemented. Take the diff of that branch also. So it would be something like this.

git archive <branch name>| tar -x -C <directory to save the branch status> 
If someone needs an example git archive develop| tar -x -C ../feature-diff.

OK now go to the directory that has the diffs. In my case, it would be one step ahead of the project root directory. And now what you have to do is get the diff from master and your feature branch and save it to a patch. In the terminal paste the following command with relevant changes.

diff -ruN <master branch diff saved directory>/ <your diff saved directory> > <something>.patch

You may need an example. the command should be something like following.

diff -ruN master-diff/ feature-diff > feature.patch

And this may take a couple of minutes based on the project size and the diff size. After the command executed there will be a patch file named as feature.patch. So if you want to separate the commits into two new branched you need to have two separate patches with the master and feature branch. If you want to separate commits to n new branched then you need to have totally new different patched with unique names.
OK, now we are almost there. Open the patch file with a separate editor. I used gedit. And remove unwanted changes from the patch file. You need to remove the changes with blocks. A block would be started with a long command started with diff and followed by the changes you’ve done.

After the changes are made save the patch file with the latest changes. Now you removed some changes from the patch file. Open the other patch file and remove the changes that are in the previously edited patch. At the end of the day when you combine the two different patch files, there should be a patch file that has all the changed in the feature branch.
OK, now you have totally different patch files that are ready to apply. Create two new branches (or n new branches based on your requirement) and apply the patch files to the branches. Use the following command to do it.
You can see whether your patch file can be used to update the branch by running a dry run.

patch -p1 — dry-run -i <patch file>

If the above command runs without giving any error you can apply the patch by using the below command.

patch -p1 -i <patch file>

And make sure you are in the newly created branch that you want to apply the patch. OK, now you can see the changes. It’s all yours now. Commit the changes and make a pull request with the relevant branch.
You may be lost in the patch file editing process. Just search on the search engine with the problem you occurred. There will be always a solution.
Cheeeeeers!!!!!
x

1 comment:

  1. These are great insights. It was very informative. Although most browsers can be used for Automated website testing across platforms, Safari and IE are the biggest roadblocks because they are OS-specific. A Mac could have a few virtual machines that run Windows or Linux. Or just Windows, since Chrome and Firefox (clones) are the main browsers for Linux. This way, you don't need to create a new OS each time. If there are any problems with the VM, you can just kill it and start a fresh one.

    ReplyDelete