Search code examples
gitversion-controlgit-commitgit-pushgit-remote

Hot fix between two remote git repositories


I have two git remote repositories, one is for test and the other is for production.

    git remote -v
    production      https://[email protected]/deploy/pr1.git (fetch)
    production      https://[email protected]/deploy/pr1.git (push)
    test    https://[email protected]/deploy/pr1_test.git (fetch)
    test    https://[email protected]/deploy/pr1_test.git (push)

When someone make a change, they work locally and push to the testing remote:

    git push test master

Someone makes the pull, test the change and if tis OK, push it to production.

    git push production master

The problem is when i have various changes to test before push to production, but i need to apply an inmediate hotfix. I cant push the hotfix to production without push al the others changes that are before it (not tested yet).



example:

    test repository : 
    test commit 6 - hotfix (i fix something) 
    test commit 5
    test commit 4
    test commit 3 - to this point is equal to production.
    test commit 2
    test commit 1
    Production repository: 
    production commit 3
    production commit 2
    production commit 1

I want to push the hotfix commit (commit 6) without push to production commit 4 and 5. Is possible to do this?

Thanks.


Solution

  • The trouble is that you're using repos to do what branches are meant for. Out of curiosity, how do you deal with situations where a commit is rejected (but the commits after it are fine)?

    Any solution (other than moving to a branch strategy suitable to your needs, after which you will likely find that a single repo would be not only sufficient but easier to deal with) is going to be messy.

    All of the possible options boil down to rebasing commit 6 onto commit 3. You don't really want that rebase going back into your test repo, as it will create a mess for all the developers. But if that rebase doesn't go back to test, then eventually it has to be removed from production as well in order to get the repos back in sync.

    Test Repo
    1 --- 2 --- 3 --- 4 --- 5 --- 6 <--(master)
    
    Prod Repo
    1 --- 2 --- 3 <--(master)
    
    Local
    1 --- 2 --- 3 --- 4 --- 5 --- 6 <--(master)
    

    Do a rebase; replace the commit numbers in this command with the corresponding SHA ID

    git checkout master
    git checkout -b temp_master
    git rebase --onto 3 5
    

    Now you have

    Test Repo
    1 --- 2 --- 3 --- 4 --- 5 --- 6 <--(master)
    
    Prod Repo
    1 --- 2 --- 3 <--(master)
    
    Local
    1 --- 2 --- 3 --- 4 --- 5 --- 6 <--(master)
                 \
                  6' <--(temp_master)
    

    Now you must test 6'. This is a new state of the code that never existed before, and it is untested. If 6 inadvertently depends on something in 4 or 5, then 6' is broken.

    So you test, it works. To get the hotfix into production

    git push production temp_master:master
    

    yielding

    Test Repo
    1 --- 2 --- 3 --- 4 --- 5 --- 6 <--(master)
    
    Prod Repo
    1 --- 2 --- 3 --- 6' <--(master)
    
    Local
    1 --- 2 --- 3 --- 4 --- 5 --- 6 <--(master)
                 \
                  6' <--(temp_master)
    

    Now my advice is to finish acceptance testing of 4 and 5 ASAP, and then force push master to production and delete temp_master.

    If you find you have to push 4 before 5 is ready to go, the it too will have to be rebased onto 6'.

    git rebase temp_master 4
    git branch -f temp_master
    

    (where again 4 is replaced with the commit's SHA).

    Again, stop and retest, because something in 6' might interact badly with 4 so 4' is a new and untested state of the code. All is well? Then:

    git push production temp_master:master
    

    and you get

    Test Repo
    1 --- 2 --- 3 --- 4 --- 5 --- 6 <--(master)
    
    Prod Repo
    1 --- 2 --- 3 --- 6' -- 4' <--(master)
    
    Local
    1 --- 2 --- 3 --- 4 --- 5 --- 6 <--(master)
                 \
                  6' --- 4' <--(temp_master)
    

    At this point, you might think that when you've tested 5 you might as well rebase it and just keep on trucking with the re-ordered branch in production. Don't, unless you're willing to reorder the branch in test (and in everyone's local repo) as well, which will be a hassle. At the end of the day, you need a common history, because even if you rebase 5 to get

    Local
    1 --- 2 --- 3 --- 4 --- 5 --- 6 <--(master)
                 \
                  6' --- 4' --- 5' <--(temp_master)
    

    you may find that 6 and 5' look the same - they have the same cumulative set of changes and the same result tree - but they are different commits and work based on one would have to be rebased to the other.