0

I squashed initial commits in master to one commit using git rebase, generating a new squashed commit, but on develop branch, the commits remain as it is. How do I replace the old commits with new squashed commit in master to develop and other feature branches?

Current State

I--A--B                     :Master
       \ C--D               :Develop

After Squashing

I--S                        :Master
 \ A--B--C--D               :Develop

What I want

I--S                        :Master
   \ C--D                   :Develop
PrivateOmega
  • 2,509
  • 1
  • 17
  • 27

1 Answers1

0
git rebase Master Develop

This command applies A, B, C and D onto S. Because the changes of A and B have already been included in S, they are skipped. Only C and D will be reapplied. The history of Develop will be:

I--S--C'--D'      :Develop

And the history of Master is unchanged:

I--S              :Master

You may encounter conflicts during the rebase. If any occurs,

  1. run git status to find the conflicting files;
  2. edit the files until they have the right contents;
  3. run git add <files>;
  4. run git rebase --continue.

My understanding on git rebase --onto A B C, in bash:

commits=$(git rev-list --reverse B..C)
# if C is not a branch name, it leads to detached HEAD state.
git checkout C
git reset A --hard
for c in $commits;do
    git cherry-pick $c
done

A, B, C are commit-ish. It's just a rough simulation. Some commits may be skipped like merge-commits and commits whose changes have been included beforehand by other commits.

ElpieKay
  • 27,194
  • 6
  • 32
  • 53
  • Thanks. I have been trying the same, but the rebase doesn't stop after B, it asks to apply the patch from rebase for every commit after B. Should I do skip after every commit after B. Does it make sense? Should I be using rebase or something to replace just A and B with S? – PrivateOmega Mar 11 '19 at 09:36
  • 1
    @KiranMathewMohan Commits after `B` will be applied by default. Their commit hashes are changed as expected. It's impossible to replace just `A` and `B` with `S` while keeping `C` and `D` unchanged. The hash of `C` is generated by the metadata including the hash of its parent `B`. If its parent now becomes `S`, the metadata is changed as well. Naturally as a result, its hash is regenerated. In fact, a new equivalent commit `C'` is created to replace `C`. So is `D`. You can choose to not apply `C` and/or `D` by interactive rebase with the option `-i`. – ElpieKay Mar 11 '19 at 09:56
  • Thanks. Will try it out. – PrivateOmega Mar 11 '19 at 10:02
  • Do you know anything about git rebase --onto. Is it any good for this situation? I am kind of confused about the concept and use of it. – PrivateOmega Mar 11 '19 at 10:40
  • @KiranMathewMohan `--onto` can be used in this case, but not necessary. The command can be written as `git rebase --onto S Master Develop` or `git rebase --onto Master Master Develop`. The formula `git rebase --onto X branchA branchB` 1) finds all the commits that are not reachable from branchA while reachable from branchB (A, B, C and D in your case); 2) applies the 1st of them onto X, and the 2nd onto the 1st, ..., and the Nth onto the (N-1)th; 3) makes `branchB` point at the Nth new commit. – ElpieKay Mar 11 '19 at 11:18
  • Thanks for the explanation on `--onto`. Anyway I have tried like you answered, but `git rebase` stopped for develop, but there are some more commits in `origin/develop` which haven't been reflected in rebased develop branch. – PrivateOmega Mar 12 '19 at 04:17
  • This git's branching is so wrong and complicated that I am confused whether to push as it is. Btw so if we are done rebasing, other branches that were originated from develop also might need to be rebased right? Also should I merge origin/develop back to develop to get the missing changes? – PrivateOmega Mar 12 '19 at 04:24
  • After the rebase is done, `origin/develop` should have more commits than the new `develop`, because `origin/develop` is coincident with the old `develop` and during the rebase some commits of the old `develop` are dropped. I have no idea about your real branches, so I cannot tell if the "missing" commits not reflected in the new `develop` are a mistake or a normal result. Don't get stuck in the number of commits, but focus on the file contents of the new "develop". If the contents are as right as expected, then everything is okay. – ElpieKay Mar 12 '19 at 06:25
  • 1
    It's better to rebase other branches originated from `develop` if you will still make new commits to them. `origin/develop` will be updated after your next push, fetch or pull on `develop`. If the rebase does lose some commits, find them out and apply them by `git cherry-pick`. Don't merge `origin/develop` to the new `develop`. Otherwise it will make the rebase meaningless at all and the history chaotic. – ElpieKay Mar 12 '19 at 06:29
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/189861/discussion-between-kiran-mathew-mohan-and-elpiekay). – PrivateOmega Mar 12 '19 at 07:39