I have set up git for my own use--so I can access a project from 'anywhere', and keep version safety if I happen to be working on part X over here, and part Y over here, and can merge if necessary.

However, only one of my development machines has a static IP. My brain is stuck in CVS mode, so I tried to set up git to have that machine be the 'central' server, which all others pull from.

This sort of works. I have a bunch of machines A-C which do a git-pull from the 'master' M. They do git pushes to send the data back.

The problem comes if I do development on the master. First, I can't figure out how to get the central repo to provide the latest version without doing

git reset --hard HEAD

which seems a bit excessive. And if I do development on the central machine before resetting, I'm not sure how to merge it with changes that have already been pushed up.

Something about my mental model is way off. Help?

  • When you say "master", are you talking about the master repository or about the master branch? – innaM Dec 10 '09 at 20:21
  • master repository – Alex Feinman Dec 10 '09 at 20:39
  • 1
    "master" in git context is usually the name of the default branch. – innaM Dec 11 '09 at 8:05
  • this probably belongs on SO – Ken Liu Jul 15 '12 at 2:11

You want your central repository to be bare. Say the machine it lives on is named static:

$ ssh static git init --bare /git/myproject.git

This bare repository is a central rendezvous point: it's for pushing to and pulling from, not development.

Do your development on clones of the central repository:

$ cd ~/src
$ git clone static:/git/myproject.git

Even if you're on static, work in a clone:

$ git clone /git/myproject.git

Although you're the only one working on this repository, get in the habit of doing your work on what the git documentation calls topic branches. An immediate benefit of this is that it keeps a clean master, that is you can always pull from your central master branch into your current local repository's master with no merging.

For example:

$ git checkout -b fix-bug-in-foo
$ hack
$ git add file.c file.h
$ git commit -m "Fix ..."

That may not seem like a big deal, but it gives you the freedom to leave the project as represented on that branch in a partially cooked state, or if your cool idea turns out to be a flop, you can easily throw away that branch without breaking anything else in your project that's already working on other branches. Infinite free mulligans!

Maybe you go home that night and added a new feature. The next morning, you

$ git checkout master
$ git pull

to update your local master to reflect what's in the central repository.

But now say you've fixed the foo bug and are ready to include it in your master branch. First you want to integrate it with the changes from last night:

$ git checkout fix-bug-in-foo
$ git rebase master

The rebase command makes your repository look as though you fixed the foo bug on top of last night's new feature. (This is sort of like svn update, but more flexible and powerful.)

Now to get it into your central master:

$ git checkout master
$ git merge fix-bug-in-foo
$ git push origin master

We've been treating master as special, but that's only conventional. You can share work on different branches of different repositories through the git repository on static just as easily.

| improve this answer | |
  • 1
    Awesome answer, nails down all of the issues at hand. – Dan Loewenherz Dec 10 '09 at 21:25
  • My git install is not accepting --bare as an option to git init (old version??), but I worked around it by cloning --bare my existing repo, and then manually editing the config files a bit. – Alex Feinman Dec 11 '09 at 13:58
  • If you're running git 1.6.4.x, it's git init --bare with no other arguments. It will use either the current working directory or GIT_DIR environment setting if set. I believe you need git 1.6.5.x for it to take a directory argument. – Darren Hall Dec 11 '09 at 15:32
  • 4
    That's the best git workflow explanation I've seen so far for the work that I'm doing. – Greg Graham Dec 12 '09 at 4:23

If you have a central server with a central git repository, that repository should be a bare repository. Bare repositories don't have working copies of the files in them. Consequently, if you are working on that central machine, you don't work with the central repository directly, but with a local clone.

| improve this answer | |

This answer is similar to gbacon's answer, but takes an approach that you already have a local repo setup, and want to create a remote master that is treated as a central repo. It's just adding details from a different approach.

I use git to store my dot-config files. I push and pull from what I consider a 'central repo'. It's quite convenient to reset all my dot files through multiple computers.

$ ssh example.com
$ mkdir dotconf.git && cd dotconf.git
$ git init --bare
$ exit

This created an empty bare repo on the repo site.

Now if I already have an existing repo locally, I can push that to the remote site.

$ cd ~/src/dotconf

chdir into the local directory.

$ git remote add origin ssh://example.com/~/dotconf.git

Add the remote repo as the origin, so push/pull will act upon that repo.

$ git push origin master

Push my master to the origin (as previously labelled via the git remote). Now that remote repo is treated as my 'central repo'. All my git push/pull will interact with the origin.

If I go to another host, I can easily pull via clone that repo to a new location.

$ git clone ssh://example.com/~/dotconf.git

If I want to do development ON the remote server, I clone first, then push/pull back into the bare repo.

$ cd ~/src
$ git clone ~/dotconf.git
$ cd ~/src/dotconf
  * do coding *
$ git push
  * check in from another location *
$ git pull

You'll likely have to set your git config --add branch.master.remote origin so git pull doesn't complain that you're not being specific enough. The other alternative is to set your master branch to --track the remote origin. Useful if you have multiple branches.

| improve this answer | |

I was just researching this same problem today. This blog post has a lot of discussion on the issue, but the majority opinion is to do what Manni said. Look at a comment on the post by David French for some other possibilities, including what to do if you do end up mistakenly pushing to a repository that has uncommitted work in the index or working tree. "git reset –soft HEAD^" will back out the pushed change without disturbing your work.

| improve this answer | |
  • 2
    One problem with that blog post is skipping the usefulness of the index. Here's a good article to explain how to work with git instead of in spite of git - osteele.com/archives/2008/05/my-git-workflow - workflow diagrams are included. – Darren Hall Dec 10 '09 at 21:51

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.