56

We use a subtree deployment a lá this Gist to deploy a subdirectory of our Yeoman project. In our case, the branch is called production, not gh-pages.

This worked perfectly until yesterday when the Git server rejected the command git subtree push --prefix dist origin production, saying

 ! [rejected]        9fe1683aa574eae33ee6754aad702488e0bd37df -> production (non-fast-forward)
error: failed to push some refs to 'git@gitlab.sdstate.edu:web-and-new-media/graduation2015.git'
hint: Updates were rejected because a pushed branch tip is behind its remote
hint: counterpart.

If I switch to the production branch locally (which is clean), git pull returns Your branch is up-to-date with 'origin/production'. even if I use the --rebase option.

I can see the contents of the production branch on the server through our web UI and there's nothing there that shouldn't be, just the compiled output of our dist directory like I'd expect.

To that end, it seems like I should safely be able to force an overwrite of these files, but how? git subtree push doesn't have a --force option.

ele
  • 6,021
  • 5
  • 25
  • 35
  • The command `git subtree split --prefix dist origin production` also fails: `fatal: ambiguous argument 'origin': unknown revision or path not in the working tree.` – ele Oct 16 '15 at 15:55
  • Well, now I'm really stumped. I ran `git subtree pull --prefix dist origin production`, which did leave me with a merge conflict related to the code I'd changed so I fixed that and ran `git subtree push --prefix dist origin production` again...only to fail with the same error again. – ele Oct 16 '15 at 18:26

4 Answers4

94

The trick was to chain the subtree split into a forced push:

git push origin `git subtree split --prefix dist master`:production --force

I got this from the Addendum of http://clontz.org/blog/2014/05/08/git-subtree-push-for-deployment/, who actually references this answer on Stack Overflow. I had skimmed this one earlier but Steve Clontz's post made it click for me.

Community
  • 1
  • 1
ele
  • 6,021
  • 5
  • 25
  • 35
  • 1
    This solution failed with "fatal: ambiguous argument 'publish-dev': unknown revision or path not in the working tree." – xinbenlv Jun 28 '16 at 05:59
  • Did anyone solve the fatal ambiguous argument issue? – Adam Reis Aug 14 '16 at 00:29
  • 1
    For fatal ambiguous argument, use -b prefix for branch name – Adam Reis Aug 14 '16 at 00:36
  • 2
    FYI: When used with Github Pages, this resets your custom domain name. – Constant Meiring Jul 03 '17 at 20:40
  • @ConstantMeiring Yeah it appears that you have to manually duplicate the CNAME file (which contains the domain name). – Greg Schmit Dec 24 '17 at 02:01
  • 3
    Could you explain more about what origin, master, & production are? – Demodave Jan 11 '19 at 18:01
  • 4
    unknown option prefix – Demodave Jan 11 '19 at 19:27
  • Initial source: https://stackoverflow.com/questions/12644855/how-do-i-reset-a-heroku-git-repository-to-its-initial-state - For the sole purpose of *enforcing git push* you may want to replace `production` with `master` too. So it should rather be: `git push origin \`git subtree split --prefix dist master\`:master --force` - the parameter `origin` you can also replace with your Git repository URL if you're here purely for Heroku - hope that helps – Greg Wozniak Oct 29 '20 at 15:11
  • this just deletes the `gh-pages` on me. – sshanzel Jan 20 '21 at 10:58
  • if you see "cannot delete master branch", then make sure you are running the command from repository root – Drdilyor Jun 13 '21 at 13:47
26

I've just enhanced the answer of ele adding generic expressions <> to make it more clear:

git push <remote> `git subtree split --prefix <local-folder> <local-branch>`:<remote-branch> --force

Example values

<remote>

origin
other-origin-name
https://github.com/full-url/of-repo

<local-folder>

Local folder path relative to repo root e.g.: /dist (you need to execute this command in root btw)

<remote-branch>

master
any-other-branchname
gazdagergo
  • 6,187
  • 1
  • 31
  • 45
  • If you have a server trying pull these changes, `git pull origin ` won't work. But this will: `git fetch --all && git reset --hard origin/` – kevnk Apr 11 '23 at 16:58
  • Warning: I must've put in the wrong branches when running this command because it deleted my remote branch. It was easy to push my subtree branch after I deleted it and wasn't a problem in the end, but there may be cases where you don't want your remote branch deleted... so be careful! – kevnk Jul 06 '23 at 17:46
4

There is a simpler solution

This always works for me.

  1. Set up a bash script which helps you do the following:
cd dist
git init
git add .
git commit -am "deploy"
git push --force <remote URL> master
rm -rf .git
cd ..

This creates a new git repository in the subdirectory you specify and force pushes everything from there.

  1. profit
raphtlw
  • 117
  • 1
  • 3
  • 8
0

There is actually a solution that is much more simple.

Source: https://gist.github.com/cobyism/4730490#gistcomment-2337463

Setup

$ rm -rf dist
$ echo "dist/" >> .gitignore
$ git worktree add dist gh-pages

Making changes

$ make # or what ever you run to populate dist
$ cd dist
$ git add --all
$ git commit -m "$(git log '--format=format:%H' master -1)"
$ git push origin production --force
$ cd ..
binarymason
  • 1,351
  • 1
  • 14
  • 31