Take an entire branch and rebase it on another commit

51 Views Asked by At

I recently inherited some PHP code that was a mess. It had harcoded paths and URLs all over the place, which I had to change every time I move the code from my test server to the production server. I ended up creating a new "production" branch separated from the "master" one, where I changed all the hardcoded paths and URLS to the ones used in the production server. In other words:

A - B - C
        \
         \-D - E

C is the master branch where I work. In it, the URLs and paths correspond to my test server. I created a new "production" branch (D and E), where I changed the paths to the production server.

Now I have added some new features to the master branch:

A - B - C - F - G - H
        \
         \-D - E

And I want to apply those D and E commits where I changed the paths and URLs to the latest changes, to H.

From what I read, rebase seems like the exact feature for this, but:

  1. The docs I read suggest that it's a bad idea to rebase branches that have already been pushed to the remote server, which is exactly what I've done.

  2. In my case, the "production" branch has two commits (because there were so many paths to change that I forgot some of them at first), so I don't know exactly if I can take all of them and rebase them entirely.

I am using Sourcetree on Windows and Mac, although I can handle the command line too.

2

There are 2 best solutions below

0
Ujjwal Raut On BEST ANSWER

Use git rebase in this case. There could be chances that some code conflicts can occur, but those can be solved manually, provided the conflicting files are textual files - code files, json files, etc.

Used it plenty of times, and if used rightly, no issues occur and the child branches can be then merged easily into main branch.

As a rule-of-thumb for me, I squash commits on the child branch into one commit using git rebase -i HEAD~<no.of.commits.to.be.squashed>, so then if any rebase conflicts occur, I can resolve them for one commit only.

6
Lajos Arpad On

Your approach is to have a branch for each possible value combinations that you might have. This means that whenever some new attribute is added, you will always need to have as many commits as the number of branches. Also, when you change a value, you will also need to apply that on as many copies as you have. Finally, you might have some secret values which should not be versioned, such as passwords, API secrets etc.

Instead of the insecure and superfluous approach that you have chosen, an alternative and arguably better way to solve your problem is the following:

1. Create an env file where you set all the values of the settings in your local

Create .env.php and set all the values to your local

2. Add .env.php to .gitignore

We don't want to version .env.php, because it is volatile and it may contain secrets that should not be versioned

3. Change all references to these settings

Go through your code and replace all the hard-coded URLs and whatnot to these settings.

4. Copy env.php to all copies of the repository

After you copied this file to all copies of the repository, change the actual values that should be used there

5. Sync

Pull the changes on all your branches or merge them into these branches, so the settings will be dynamically inferred based on .env.php

6. You may want to have multiple unversioned configurations

Conclusion

Instead of replicating all your branches to as many branches as you have, make sure that you infer them dynamically and you have an unversioned copy of .env.php with those values. At the first instance, you could implement this function into .env.php:

function env() {
    return [
        "key1" => "value1",
        "key2" => "value2",
        //...
    ];
}

and include or require this file so, instead of URL1 you would do something like env()["URL1"]