How to realise a deployment branch in Git

I’m using git for a PHP project, I think it’s really handy. There is one thing that would be great if I get it to work.

I have created a branch, meant for deployment. It has some differences, like different configuration files and documentation.

  • Git Workflow leads to Unsyncronized Branches on Bitbucket
  • How should I apply the git-flow paradigm to my project?
  • Git Rebase from Remote Master
  • Mercurial branching and bookmarks
  • Sourcetree Failed to push some refs to repository
  • Why do files in the working directory get the modified status on switching between Git branches?
  • I can’t just ignore them, because then they will stay in both branches, while I would like to keep them different in both branches.

    The problem is that when I merge the branches, those files that are meant to be different are merged too.

    Is there any convenient way to accomplish such a thing? How is this normally done?

  • How to handle a large git repository?
  • If I have merged a Git branch to master, can I delete the branch itself?
  • Syncing a fork in Bitbucket, Branches and are they synced?
  • GIT diff and GIT status ignore changes of a file
  • Git merge fails unexpected
  • TortoiseGit - Multiple GitHub repositories with different key pairs each
  • 10 Solutions collect form web for “How to realise a deployment branch in Git”

    I am not sure Git is meant to be used this way.

    First a quick Linus advice, always “colorful” and informative 😉

    Git very fundamentally tracks project state, not file state. Which means that you very much can NOT try to “merge a file”. It is a senseless operation in git, and in fact, any SCM that allows it pretty much is doomed to be a total piece of sht ().

    (*) And I’m not saying that just because git doesn’t do it. It’s much more fundamental than that. Once you start doing per-file branching and merging, you’ve basically screwed yourself, and you’ll never be able to work on the project as a “whole project” any more – you no longer have a well-defined history that actually is the history of the whole project.


    That said, you could:

    • manage those config/doc files a separate git sub-projects (note: the use of submodules has been discussed here)
    • or record partial merge (using “ours” strategy for files we don’t want to merge), then –amend it.

    Other solutions in this thread involve working on a “server-specific” branch on your deployment server

    Development        Deployment
    x--x               $ git clone
                       # master
                       $ git checkout -b deployment origin/master
                            -- #deployment
                       $ .... #makes changes for config files
                              #or other specific deployment files
                            --d1--d2 # no need to push that branch ever.
    #new developments
                       $ git pull --rebase #pull origin/master and 
                                           #replay current branch on top of it
                                  --d1'--d2' #SHA1 rewritten in deployment branch
                                             #not important since this branch 
                                             #is not pushed (published)

    This works for me, and I make only minor configuration changes to deploy (3 lines in config files).

    1. Clone your repository from GitHub or wherever you keep it. To where you wish to deploy.

    2. Run git checkout -b deployment origin/master.

    3. Make your changes (push them if you like).

    4. Whenever your master (or whatever branch you made the deployment from) has changes you want to deploy, simply git pull --rebase.

    It’s a simple solution and it certainly works for me, I can’t speak to wether or not it this makes it “shi*t” as others suggest, but it is certainly very useful for our purposes.

    I do some silly tricks like:

    • Have the app read file config
    • Add config.development and config.production but not config to the repository
    • Have your deploy script not only clone the repository, but also then cp config.production config

    Does that make any sense?

    It works okay for me.

    Quick answer is, don’t ever merge the branches. In fact you don’t need to merge them at all, just merge from development (aka “master”) to deployment to merge fixes and generic changes.

    If you want to keep your history nice, you can keep the deployment files in some commits on top of your clean branch. Then, when it’s time to deploy a new version, you check out the deployment branch and ‘git rebase master’, to put those commits on top of the original branch.

    That way, you can also make easy changes to the configuration files, and change the top commit with ‘git commit –amend’.

    I had a similar problem and created a tiny project called config-magic to help manage this.

    Config-magic lets you create template conf files and then profiles of data for each of dev/staging/production. You then run “cfg dev” to produce the “dev” config files, “cfg staging” to produce the staging config, etc.

    I then have this wired up with scripts, so that when I deploy to staging, I locally run “cfg staging” then scp over all of the config files after updating the codebase from git.

    The “actual” config files are set to be ignored by git. This has worked really well for me so far.

    I was thinking about all of these solutions for my situation but none of them seem to apply. I edit both on my live and development servers.
    Rebase works well if you dont need to republish that branch, but I make changes on my deployment branch and publish those back to the main repository.
    The submodule way only works if your files are in a seperate subdir, my config files are in several places.
    The merge ours method wouldnt work so well also since i’d have to pull that branch first and then the big branch.
    Maybe it would work if there was still a merge theirs and I could pull in the proper configuration branch when needed.
    For now a .gitignore works and I just manually upload the files.

    After doing more research I’ve found my solution to not have a git repo on the live site but use a staging site to pull the latest changes into my branch with the staging/live config files. and then deploy by git archive and extracting the files onto my live site.

    cherry-pick seems to work for this for this (at the expense of polluting the logs a bit).

    git checkout -b testing
    make changes and commit
    git checkout master
    git checkout -b deploy
    make changes and commit
    git checkout master

    do everything under master and
    git cherry-pick testing or git cherry-pick deploy to apply the diffs needed to switch from the current system into the testing or deployment version.

    I mentioned earlier patch files. I’ve gone off this now, and instead maintain deployment branches.

    ie, I branch off master with a new branch named ‘master-deployed’, and make changes on that branch that I need to be only in the test version on the build server (i.e. adding a warning that this is not the live version, and different db server in web.config).

    The build server when building the bleeding edge version then checks out master-deployed, and rebases it onto origin/master before performing the usual build. If no-one has made any conflicting changes then everything is fine. If they have then I can’t see any system handling this without manual intervention.

    Same goes for tip of qa, which has a branch ‘qa-deployed’

    I use the –onto flag to make sure if a whole branch is rewritten then the patch doesn’t take all the old commits with it.

    So on the build server the qa build looks something like

    git reset --hard
    git clean -xfd
    git checkout -f qa-deployed
    git rebase --onto qa HEAD^ qa-deployed

    currently i have a couple of patch files checked in, and the build server applies those patches for the relevant versions. though i’m having second thoughts about it at the moment

    Git Baby is a git and github fan, let's start git clone.