0

On a personal project that I am working on, I have the following situation -

                                    N'          <-- mainscreen
                                   /
                                  | N--O--P--Q  <-- database
                                  |/
A---B---C---D---------------------M             <-- master
             \                   /
              F--G--H--I--J--K--L               <-- loginscreen

Now although I have some basic level of experience with git, I never knew about any good git practices nor have I ever worked on a big complex project before which has led my skills to stagnate. So I decided to learn it properly and follow some good practices with this project. A quick search led me to this which I guess is a popular model from all the references to it.

After going through the article, I realized that due to lack of planning in my commits, some of the code in the loginscreen branch is actually common code required in the other branches and should be kept separate. So I decided to rewrite the history of the branch so that the common code is separated out into a new develop branch. I found that interactive rebasing can be used to split the commits but I am not sure if that is possible here because I have already merged loginscreen into master (which was probably a bad idea). Basically what I want to do is -


  1. Create a new branch develop based on A, the initial commit
  2. Move B, C, D commits to develop
  3. Split F - L commits such that only the code related to loginscreen is in its own branch and the common code is in develop
  4. Merge loginscreen into develop
  5. If possible, remove the merge commit M in master
  6. Rebase the database and mainscreen branches on the new develop branch

The result should be something like this -

   A-----------------------M-----------      <-- master        
    \                      | N--O--P--Q      <-- database
     \                     |/
      B---C---D---G--I--K--L                 <-- develop
               \          / \
                F---H---J    \               <-- loginscreen
                              \
                               N`            <-- mainscreen

(G, I, K commits contain the common code)

Like I said, this is a personal project and hasn't been pushed yet so there will be no issues in rewriting the history. But is this even possible?

jL4
  • 1,238
  • 10
  • 15
  • 2
    The names of the branches seem to indicate that you have multiple distinct projects going on in one repository, is that about right? If so then you should look into how to structure the code in such a way to not do that. – Lasse V. Karlsen Jan 19 '18 at 07:08
  • Not distinct projects but separate components, if you will. Like having the database code in a separate branch instead of writing it in the loginscreen branch – jL4 Jan 19 '18 at 07:12
  • If there is no commit after m on master, you can reset back to the previous, if there is, then you need to do tricky things, like create a branch from master, reset master back to m-1, then rebase/cherrypick the needed commits from the temp branch( or just reset and recommit, if you want it quick and dirty.) – MrKekson Jan 19 '18 at 12:19
  • rebaseing the other two should be no problem, but first take look at rebase ---onto, sometimes it can be lot easyer. – MrKekson Jan 19 '18 at 12:19
  • also, from the first image, you can defineteley get to the last one, but as you sad, you need to rebase/cherrypick a lot, so there can be a tonn of conflicts. – MrKekson Jan 19 '18 at 12:21
  • @MrKekson I have been experimenting on a copy of the repo since the last couple of hours and did exactly that. I created a new develop branch from the initial commit then cherry picked, rebased and merged branches as and when necessary. The history is now clean like I wanted but one issue is that the commit timestamps have changed which probably cannot be avoided. – jL4 Jan 19 '18 at 12:41
  • you can change the timestamps too, if needed, not sure what what would be the benefit tho: https://stackoverflow.com/questions/454734/how-can-one-change-the-timestamp-of-an-old-commit-in-git – MrKekson Jan 20 '18 at 02:48

1 Answers1

0

I easily solved this using cherry-pick. All I needed to do was create a new branch called develop on the initial commit then cherry-picked B,C and D. Then I created a new branch for the loginscreen commits and cherry-picked, separated the files, merged the branches and solved merge-conflicts as and when necessary. All this resulted in a state somewhat like this -

   A----------------------------------      <-- master        
    \                      
     \                             
      B---C---D--G--I--K--L--------------Q        <-- develop
               \   \     /   \          /
                F---H---J     M--N--O--P              <-- loginscreen

After this, adding the mainscreen and database branches was simple cherry-picking of the commits into their respective new branches on develop.

Bear in mind that this will change the commit timestamps and sometimes the author timestamps(when a conflict occurs). I did not bother with the commit ones but the author timestamps can be changed using git commit --amend --date.

jL4
  • 1,238
  • 10
  • 15