The most interesting difference is that you don't need a git server to use git. So having a local only Git repository of your project is perfectly OK. And you can keep it that way for ever or until you decide to share it either to other users, or between you own computers. Recommended reading about Git basics: http://progit.org/book/ch1-3.html.
When moving from my projects from Subversion to Git I did a bit of Googling on the topic and found lots of good stuff. Who da thunk it! The ones that helped me the most are listed below.
Here is the installer I used : http://code.google.com/p/git-osx-installer/
First off, lets create a new local repository with the files we are currently working on. Simply type
git init in
your base project directory. And voila we have a Git repo that we can commit, stash, branch stuff onto, into and
from.
For this step, I again turned to the tips on the Git Pro book website: http://progit.org/book/ch4-1.html.
In the terminal window it looks something like this:
~Projects/HelloWorld/> ~Projects/HelloWorld/> ~Projects/HelloWorld/> mkdir web ~Projects/HelloWorld/> mkdir web/css/ ~Projects/HelloWorld/> mkdir web/gfx/ ~Projects/HelloWorld/> touch web/index.html ~Projects/HelloWorld/> ~Projects/HelloWorld/> git init Initialized empty Git repository in ~/Projects/HelloWorld/.git/ ~Projects/HelloWorld/> ~Projects/HelloWorld/> emacs web/index.html [Insert rocket science here] ~Projects/HelloWorld/> ~Projects/HelloWorld/> git add . ~Projects/HelloWorld/> git commit -am "Initial commit" [master (root-commit) 969d8f5] Initial commit 1 files changed, 10 insertions(+), 0 deletions(-) create mode 100644 web/index.html create mode 100644 web/index.html~Shucks. Emacs cleverly backed up the original version of index.html as index.html~ which we don't really want Git to track. So we quickly create a .gitignore-file to match files like that. I found a good writeup about .gitignore over at gitready.com
~Projects/HelloWorld/> echo "*~" > .gitignore ~Projects/HelloWorld/> git add .gitignore ~Projects/HelloWorld/> git commit -am "Added .gitignore" [master 092b4eb] Added .gitignore 1 files changed, 1 insertions(+), 0 deletions(-) create mode 100644 .gitignore ~Projects/HelloWorld/> ~Projects/HelloWorld/> rm web/index.html~ ~Projects/HelloWorld/> git commit -am "Removed that file" [master f44b97b] Removed that file 0 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 web/index.html~ ~Projects/HelloWorld/>Now the project is ready to be shared across the internets so that by the power of the open source community, this app will develop into the new twitter- and/or facebook-killer-app, in time for tea. Better put the kettle on then.
However, there is one snag that we may encounter ( really, there must be thousands of possible snags, but I ran into one). Lets see. First, we upload the .git-directory to a server where others can reach our project.
~Projects/HelloWorld/> scp -r .git user@server:/opt/git/HelloWorld.git COMMIT_EDITMSG 100% 18 0.0KB/s 00:00 config 100% 213 0.2KB/s 00:00 description 100% 73 0.1KB/s 00:00 ..and so on..Then we tell git that this is not longer just a local repository, but that it has a remote origin:
~Projects/HelloWorld/> git remote add origin user@server:/opt/git/HelloWorld.git ~Projects/HelloWorld/> git remote -v origin user@server:/opt/git/HelloWorld.git (fetch) origin user@server:/opt/git/HelloWorld.git (push) ~Projects/HelloWorld/>All righty then. It looks like the project is online. Lets try a bit of editing followed pushing.
~Projects/HelloWorld/> echo "Joimaloi" >> README.txt ~Projects/HelloWorld/> git commit -am "Added more detailed documentation" [master a3e9ee5] Added more detailed documentation 1 files changed, 1 insertions(+), 0 deletions(-) ~Projects/HelloWorld/> git push Counting objects: 5, done. Delta compression using up to 8 threads. Compressing objects: 100% (2/2), done. Writing objects: 100% (3/3), 342 bytes, done. Total 3 (delta 0), reused 0 (delta 0) remote: error: refusing to update checked out branch: refs/heads/master remote: error: By default, updating the current branch in a non-bare repository remote: error: is denied, because it will make the index and work tree inconsistent remote: error: with what you pushed, and will require 'git reset --hard' to match remote: error: the work tree to HEAD. remote: error: remote: error: You can set 'receive.denyCurrentBranch' configuration variable to remote: error: 'ignore' or 'warn' in the remote repository to allow pushing into remote: error: its current branch; however, this is not recommended unless you remote: error: arranged to update its work tree to match what you pushed in some remote: error: other way. remote: error: remote: error: To squelch this message and still keep the default behaviour, set remote: error: 'receive.denyCurrentBranch' configuration variable to 'refuse'. To user@server:/opt/git/HelloWorld.git ! [remote rejected] HEAD -> master (branch is currently checked out) error: failed to push some refs to 'user@server:/opt/git/HelloWorld.git' ~Projects/HelloWorld/>Oh noes! I can't has push? The reason that this happens, AFAIU, is that when we did the
git init
we created a non-bare, or a working repository with both the files we actually work on AND the repository
with all its magic index-stuff inside the .git directory. This somehow confuses git when pushing to the remote.
ONE way fix this, we have to head over to the server
where we put the remote repo and and run this magic command mentioned on
StackOverflow
inside the git-repository.~Projects/HelloWorld/> ssh user@server Ubuntu 10.04.3 LTS Welcome to Ubuntu! user@server:~$ cd /opt/git/HelloWorld.git/ user@server:/opt/git/HelloWorld.git$ git config --bool core.bare true user@server:/opt/git/HelloWorld.git$ exit logout Connection to server closed. ~Projects/HelloWorld/> git push Counting objects: 5, done. Delta compression using up to 8 threads. Compressing objects: 100% (2/2), done. Writing objects: 100% (3/3), 342 bytes, done. Total 3 (delta 0), reused 0 (delta 0) To user@server:/opt/git/HelloWorld.git f44b97b..a3e9ee5 HEAD -> master ~Projects/HelloWorld/>Another, and much easier solution is to do a slightly different push the first time around. Read slightly more about that on GitHub. So instead of the simple push and the fix above we do this:
~Projects/HelloWorld/> git push -u origin master Branch master set up to track remote branch master from origin. Everything up-to-dateHurray! Success! I can haz a remote git repo!
Now you, and anyone with access to your git repo, can clone it and start pushing code. More information about creating shared repos can be found here on ServerFault and here on Patrick Debois blog.
Here is how you clone your project:
~/Projects/> ~/Projects/> git clone user@server:/opt/git/HelloWorld.git HelloClonedWorld Cloning into HelloClonedWorld... remote: Counting objects: 17, done. remote: Compressing objects: 100% (11/11), done. remote: Total 17 (delta 2), reused 0 (delta 0) Receiving objects: 100% (17/17), done. Resolving deltas: 100% (2/2), done. ~/Projects/> cd HelloClonedWorld/ ~/Projects/HelloClonedWorld/> dir total 16 drwxr-xr-x 6 andreasoverland 1333597109 204 Mar 8 00:00 . drwxr-xr-x 10 andreasoverland 1333597109 340 Mar 8 00:00 .. drwxr-xr-x 13 andreasoverland 1333597109 442 Mar 8 00:00 .git -rw-r--r-- 1 andreasoverland 1333597109 3 Mar 8 00:00 .gitignore -rw-r--r-- 1 andreasoverland 1333597109 14 Mar 8 00:00 README.txt drwxr-xr-x 3 andreasoverland 1333597109 102 Mar 8 00:00 web ~/Projects/HelloClonedWorld/>So a quick, short version recap:
~/Projects/> ~/Projects/> mkdir RecapProject ~/Projects/> cd RecapProject/ ~/Projects/RecapProject/> echo "Quick recap" > README.txt ~/Projects/RecapProject/> git init Initialized empty Git repository in ~/Projects/RecapProject/.git/ ~/Projects/RecapProject/> git add README.txt ~/Projects/RecapProject/> git commit -am "Initial commit" [master (root-commit) 8f5c019] Initial commit 1 files changed, 1 insertions(+), 0 deletions(-) create mode 100644 README.txt ~/Projects/RecapProject/> git remote add origin user@server:/opt/git/RecapProject.git ~/Projects/RecapProject/> scp -r .git user@server:/opt/git/RecapProject.git [files get transferred] ~/Projects/RecapProject/> git push -u origin master Branch master set up to track remote branch master from origin. Everything up-to-date ~/Projects/RecapProject/>And thats about it.
Except of course for all the branching and merging capabilities that are quite remarkable, perhaps even unique in Git. They come into play with larger development project and are very very handy for keeping the quality of the code ship shape. Good luck.