Push to a non-bare Git repository

I usually work on a remote server via ssh (screen and vim), where I have a Git repository. Sometimes I’m not online, so I have a separate repository (cloned from my remote) on my laptop.

However, I can’t pull from this repository on remote side because I’m usually behind a firewall or I don’t have a public IP.

  • How to switch entire XCode project to previous commit
  • How to shrink Git repo and better manage large files
  • How to setup github repository in my NetBeans IDE?
  • How can I change the highest directory in a git project?
  • Squash commits on master but separate commits on feature branch?
  • How to use git pickaxe option with special characters like 'ñ or á' in ANSI encoded files?
  • I’ve read that I should push just to a bare repository. How should I then push my changes to my remote repository?

  • Failure build on Maven release plugin
  • Naive Git setup, Is it possible to untrack files which are listed on my .gitignore?
  • Git: fix noobish mistake to avoid rebase hell
  • Buildkite and webhook to git repo
  • Any way to guarantee that a git user doesn't use fake account info when commiting and pushing?
  • Git Attributes Merge Ours
  • 4 Solutions collect form web for “Push to a non-bare Git repository”

    receive.denyCurrentBranch updateInstead, added in Git 2.3, also updates the server’s working tree if it is clean.

    So if you ensure that you always commit before you pull locally, and keep a clean working tree on the server (which you should do to avoid having merge conflicts), then this option is a good solution.

    Sample usage:

    git init server
    cd server
    touch a
    git add .
    git commit -m 0
    git config --local receive.denyCurrentBranch updateInstead
    
    cd ..
    git clone server local
    cd local
    touch b
    git add .
    git commit -m 1
    git push origin master:master
    
    cd ../server
    ls
    

    Output:

    a
    b
    

    Best Option

    Probably the cleanest, least confusing, and safest way to push into your non-bare remote repository, is to push to dedicated branches in the remote that represent your laptop branches.

    Let’s look at the simplest case, and assume you have just one branch in each repo: master. When you push to the remote repo from your laptop, instead of pushing master -> master, push master -> laptop-master (or a similar name). This way the push doesn’t affect the currently checked-out master branch in the remote repo. To do this from the laptop, the command is pretty simple:

    git push origin master:laptop-master
    

    This means that the local master branch will be pushed to the branch named “laptop-master” in the remote repository. In your remote repo, you’ll have a new branch named “laptop-master” that you can then merge into your remote master when you are ready.

    Alternate Option

    It’s also possible to just push master -> master, but pushing to the currently checked-out branch of a non-bare repo is generally not recommended, because it can be confusing if you don’t understand what is going on. This is because pushing to a checked-out branch doesn’t update the work tree, so checking git status in the checked-out branch that was pushed into will show exactly the opposite differences as what was most recently pushed. It would get especially confusing if the work tree was dirty before the push was done, which is a big reason why this is not recommended.

    If you want to try just pushing master -> master, then the command is just:

    git push origin
    

    But when you go back to the remote repo, you’ll most likely want to do a git reset --hard HEAD to get the work tree in sync with the content that was pushed. This can be dangerous, because if there are any uncommitted changes in the remote work tree that you wanted to keep it will wipe them out. Be sure you know what the consequences of this are before you try it, or at least make a backup first!

    EDIT Since Git 2.3, you can use “push-to-deploy” git push: https://github.com/blog/1957-git-2-3-has-been-released. But pushing to a separate branch and then merging is usually better since it does an actual merge (hence works with uncommitted changes just like merge does).

    I would suggest to have a bare-repository and a local working (non-bare) repos in your server. You could push changes from laptop to server bare repo and then pull from that bare repo to server working repo. The reason I say this is because you might have many complete/incomplete branches in server which you will want to replicate on the laptop.

    This way you don’t have to worry about the state of the branch checked out on server working repo while pushing changes to server.

    Another option is to setup a reverse ssh tunnel so that you can pull instead of push.

    # start the tunnel from the natted box you wish to pull from (local)
    $ ssh -R 1234:localhost:22 user@remote
    
    # on the other box (remote)
    $ git remote add other-side ssh://user@localhost:1234/the/repo
    $ git pull other-side
    

    And if you want the tunnel to run in the background

    $ ssh -fNnR 1234:localhost:22 user@remote
    
    Git Baby is a git and github fan, let's start git clone.