Problem
I have a repository with several different files, and I have had to modify several.
Since each one is a configuration file for different projects, my intention was to create a branch for each of them, like this (alphabetical order is the time order of commits) :
a--b--c (develop)
|\
| d--e--f (feature/1)
|\
| g--h--i (feature/2)
\
j--k--l (feature/3)
The problem is that I forgot to create the branches from develop, so in the end I have this:
a--b--c (develop)
\
d--e--f (feature/1)
\
g--h--i (feature/2)
\
j--k--l (feature/3)
And to top it all off, I've already done it push
remotely.
What have I thought of doing?
I have thought about doing rebase
:
git rebase --onto develop feature/3 feature/4
git rebase --onto develop feature/2 feature/3
...
But I understand that this could be a problem when redoing push
remotely, because the tree in remote would not be the same as the one in local.
My other option was to delete both the local and remote branches and do it all over again. It's really only one file per branch, and it's only a couple of lines per file, so I could do it in a couple of hours, but I'm sure git has some way around this.
what do i want to get
I want the branches that I have created to all be born from the same commit develop
(the last one) and that the changes I made in the first ones are not reflected in the last ones, always trying to make sure there are no problems when pushing.
By way of consideration, in these branches I am working only myself.
I have created a "fake" repository to test if what you propose in the question would work (TL;DR: it works )
After creating the initial branch structure, and making a clone of the repository, from the clone I see:
(You don't see much here, since the story is linear from A to L, each branch building on the previous one)
I execute the commands that you yourself propose:
This changes the hashes of all commits (because it creates new ones). The new structure appears like this. It's confusing and cumbersome because you can still see the remote branches with their original linear structure (
origin/feature/1
,origin/feature/2
, etc) along with the new branches "moved" to your site:Now we upload the changes to the remote. Since a
push
normal will fail (because the hashes have been changed), you have to force it:After this, the remote branches remain the same as the local ones, and the tree is simplified and matches what you were looking for:
To check that the thing also works as expected, what I had done in each commit was simply create a file called
a.txt
,b.txt
, etc (with the name of the commit). Now I can verify that if I do only the files , and ,git checkout develop
are visible , and that if I go to , for example , in addition to the three previous ones I can see , but not .a.txt
b.txt
c.txt
git checkout feature/2
g.txt h.txt i.txt
d.txt e.txt f.txt
It's supposed to let
git rebase --onto
you rewrite history between two commits so that what's in between is removed from history. I'm not sure what you want to do by passing it three parameters.In your case, I would think the following: If each branch is develop + a couple of changes (desired structure):
So we could squash (for example)
e
andf
ond
because, well, three commits is a lot for a simple and theoretically atomic change (as a feature of this type should be). In that case your desired structure ( squashed edition ) could be written as:A change like that would be harmless and of course you would have to use
git push -f
because after the rebase the hash will have changed.Now think about the following: you accidentally ended up with the structure ( cascade structure ):
You can bring the waterfall structure to the squashed edition structure by doing
With that you arrive at:
If you notice, I stood on each branch, pointed the HEAD to develop, and generated a commit that contains just the difference between that branch and develop.
The hashes are different (they never repeat even if the file has the same content) but if you were to check out the file
diff
to manually apply it as a patch, they would be identical.Good luck!
One option to avoid
push --force
is: