Home > Blockchain >  A new commit to git parent branch and propagate these changes to child branches
A new commit to git parent branch and propagate these changes to child branches

Time:01-29

I have a branch feat-1 based off develop. I did some commits in feat-1, and created pull request to merge feat-1 into develop. While waiting for the pull request to be merged, I created a new branch feat-2 based off feat-1 to work on a new feature that depends on code in feat-1. My work in feat-2 was done, and I needed to work on a new feature that depends on feat-2. So I created a new branch feat-3 based off feat-2.

develop
        \
         feat-1
                \
                    feat-2
                            \
                            feat-3        

Now, there are some changes that need to be done in feat-1. These changes would conflict with feat-2 and feat-3. When I commit this changes in feat-1, how do I propagate those changes to feat-2 and feat-3?

If I merge feat-1 into feat-2 then I would have to merge feat-2 into feat-3, and so on. That way I may have to handle the same conflicts several times.

Is there a way that I just have to handle the conflicts once?

CodePudding user response:

Is there a way that I just have to handle the conflicts once?

Yes absolutely, by using the explicit onto three argument form of rebase.

Test repo

To recreate your scenario I created a test repository which has a changelog file that each commit adds a line to so that feat-3 at the end contains:

# Changelog

## Unreleased

* Changelog added.
* Added feature 1.
* Added feature 2.
* Added feature 3.

and to create a conflict a readme is added on develop after feat-1 was branched out:

# Changelog

## Unreleased

* Changelog added.
* Added readme file.

gitk --all screenshot

Step 1

some changes that need to be done in feat-1.

For instance rebasing feat-1 on top of the latest develop.

But before starting any rebasing, let's create a couple of branches to hold references to what branches were before the rebase started.

$ git branch feat-1.old feat-1
$ git branch feat-2.old feat-2
$ git branch feat-3.old feat-3

Rebasing of feat-1 on top of develop will of course results in a conflict because both branches has added different things at the same place:

$ git rebase develop feat-1
Auto-merging CHANGELOG.md
CONFLICT (content): Merge conflict in CHANGELOG.md
error: could not apply 0a7176f... Added feature 1
hint: Resolve all conflicts manually, mark them as resolved with
hint: "git add/rm <conflicted_files>", then run "git rebase --continue".
hint: You can instead skip this commit: run "git rebase --skip".
hint: To abort and get back to the state before "git rebase", run "git rebase --abort".
Could not apply 0a7176f... Added feature 1
$

You should never, never, never, never, ever settle for anything less than a tool with proper 3-way merge support to resolve such conflicts. My favourite is KDiff3 screenshot

where in this particular case, the correct resolvement was accepting B's change and then C's change.

Update CHANGELOG.md with merge result? [YyNnQq] (y): 
...
$ git rebase --continue
...
$

So feat-1 is now updated and conflict resolved, and preferably this is the last time we need to deal with that conflict again...

Step 2

...and the good news is that using rebase onto three argument form we can achieve that. Starting with feat-2.

gitk --all screenshot

Since feat-2 contains the old commit from feat-1 and git thinks that the common ancestor is the parent to that commit, then that conflict would re-appear with a plain git rebase feat-1 feat-2.

gitk --all screenshot

Step 4

After the rebases, you ought to run git-test on all the new commits.

After everything is verified you can delete all the feat-*.old branches.


1 I was actually surprised today that this did not trigger a conflict since the lines changed are so close. It must have been changed from before when I think changes within -3 lines would trigger a conflict. But in that case using KDiff3 would have resolved those automatically since it is a bit more aggressive in its strategy of resolving conflicts and as long as it is not the same line that is modified, KDiff3 accepts all changes (which normally is nice but it can also occasionally accept too much).

CodePudding user response:

you rebase feat-2 on feat-1 and potentially that fixes the conflict so you can rebase feat-3 onto feat-2 without anything to fix (or still, resolving conflicts in the process)

If you dont care about linearity of git history, you can either cherry-pick commit from feat-1 onto rest of your branches, or merge feat-1 into rest of your branches.

Is there a way that I just have to handle the conflicts once?

not really as all of the branches contains its onw unique commit history, therfore you cannot apply commit in "root" of the branch and expect it to be applied backwards (because it would be "before" following changes. Even if you would remove feat-1, rest of the branches will hold commits that were in feat-1 intact as it were

You have to apply modifications branch by branch.

  •  Tags:  
  • git
  • Related