[ /howto/git ]

Using Git

Git is a versioning tool written by Linus Torvalds, after whom the Linux Kernel is named. It keeps track of the changes you make to repositories of code, so that you don't have to.

You can branch off from your main project while working on bugs, and merge your changes into the master branch when you are ready. Github is probably the best known site for hosting such Git repositories (repos). CJDNS is published on Github, as are many other open source projects.

If any of your machines are configured for ssh, you can host your own git repo without having to expose your private code, or having to pay github to host it. This places the burden of backing up your code on you, but in my opinion, decentralization is worth the extra work. If you have a webserver set up, you can use that to make your code available to anyone who can reach that server.

How to install Git

This is really easy. Practically every distro I've come across keeps Git in its standard repositories.

On Debian || Ubuntu || Mint

sudo apt-get install git

On Arch

sudo pacman -S git

On OSX with brew installed

brew install git

Then configure a few things:

git config --global user.name "Your Name"  
git config --global user.email you@yourdomain.com  
git config --global core.editor "nano"

How to pull code from Github

This is really easy. Find a repository you want to download by browsing github, maybe this simple server that I wrote.
Most repositories will have a README.md file, which is used for its front page on Github. It's a format called Markdown, which is translated into HTML.
You will generally find instructions on how to install that particular repository right here.

git clone https://github.com/ansuz/quineserv.git;cd quineserv; ./do

This creates a folder named quineserv in the current directory, downloads the repository, then changes into it, and finally runs some scripts to set up the server.
I threw that code together in about an hour, if I recall correctly. I'm sure it has some bugs. I put my energy into this site, instead. Feel free to improve it.
node quineserv.js
It is, however, sufficient to complete this tutorial.

Hosting a public repository on Github

  • First you'll need to visit github.com and create an account.
  • Then make a repository (click on things)
  • Click New Repository.
  • Fill out the information on this page. When you're done, click "Create Repository."
  • suppose you have some code... change into the directory where it's located
    cd myCode   
    git init  
    git add README  
    git add .   
    git commit -m "pewpewpew"   
    git remote add origin https://github.com/username/Hello-World.git #substitute the name of your repository here  
    git push origin master
    
  • later, if you want to remove files:
    git rm file.ext   
    git commit  
    git push origin master
    
  • Alternatively, instead of running git add beforehand, you can use
    git commit -a

Hosting a private repository on your own ssh-server

It doesn't seem to be widely known that git has many features beyond syncing code with Github
You can use it to organize your code locally, using ssh to push and pull
It isn't too difficult to set up, just a few commands each for the server and the client

SERVERSIDE

If you only want to be able to pull, you can forego the step of making a new user. It's good practice not to muck up your permissions, though.

cd /home  
sudo useradd git; 
sudo passwd git;  
mkdir ~/repos   
cd ~/repos

prepare the repository

mkdir pew.git   
cd pew.git    
git init --bare

That's it for the server, now on to the client

CLIENTSIDE

mkdir GIT   
cd GIT    
git init  
git remote add origin ssh://git@192.168.0.15/home/repos/pew.git   
git clone ssh://git@192.168.0.15/home/repos/pew.git

Now you're ready to start coding

git add README.md 
git commit -m "PEWPEW"  
git push origin master   # and finally commit!

Hosting a public repo via HTTP

Git supports this natively, I'll give an example using my own server code

git clone /path/to/repository   
git pull /path/to/repository  
git clone ssh://yourhost/~you/repository

provide extra information so the web server knows what to do with the repository.
git clone --bare ~/proj proj.git
make sure that the information gets updated any time someone pushes to the repository.

touch proj.git/git-daemon-export-ok    
mv proj.git /home/you/public_html/proj.git  
cd proj.git   
git --bare update-server-info    
mv hooks/post-update.sample hooks/post-updated

launch a server containing your repo ;)

A Bunch More Commands

check out a git repository's wiki
git clone https://github.com/user/project.wiki.git

git ls-files # list all files currently under source control

git submodule add <url> <directory> import an external repository as a module
git submodule init # initialize submodules
git submodule update # pull the files for a submodule

git log   
git remote show origin  
git pull origin   
git push origin   

git remote rm origin  #Removes old origin   
git remote add origin https://username@bitbucket.org/your.new.repo  #Adds new origin pointing to BitBucket    
git push -u origin  #Pushes commits to new repo   

git clone http://yourserver.com/~you/proj.git   
git reset --hard to remove already-published commits, # or    
git commit --amend to replace already-published commits (as in the section called “Fixing a mistake by rewriting history”), # or  
git rebase # to rebase any already-published commits (as in the section called “Keeping a patch series up to date using git rebase”).

You may force git push to perform the update anyway by preceding the branch name with a plus sign:
git push ssh://yourserver.com/~you/proj.git +master
You can configure multiple remote repos with the git remote command:
git remote add alt alt-machine:/path/to/repo
In order to fetch from all the configured remotes and update tracking branches, but not merge into HEAD, do:
git remote update
If it's not currently connected to one of the remotes, it will time out or throw an error, and go on to the next.
You'll have to manually merge from the fetched repos, or cherry-pick, depending on how you want to organize collecting changes.
To fetch the master branch from alt and pull it into your current head, do:
git pull alt master
So in fact git pull is almost shorthand for git pull origin HEAD
(actually it looks in the config file to determine this, but you get the idea).
For pushing updates, you have to do that to each repo manually. Push was, I think, designed with the central-repository workflow in mind.
-Araqnid (StackOverflow)
This something I’ve been using for quite a while without bad consequences and suggested by Linus Torvalds on the git mailing list.
araqnid’s solution is the proper one for bringing code into your repository… but when you, like me, have multiple equivalent authoritative upstreams (I keep some of my more critical projects cloned to both a private upstream, GitHub, and Codaset), it can be a pain to push changes to each one, every day.

Long story short, git remote add all of your remotes individually… and then git config -e and add a merged‐remote.
Assuming you have this repository config:

[remote "GitHub"]   
    url = git@github.com:elliottcable/Paws.o.git  
    fetch = +refs/heads/*:refs/remotes/GitHub/*   
[branch "Master"]   
    remote = GitHub   
    merge = refs/heads/Master   
[remote "Codaset"]    
    url = git@codaset.com:elliottcable/paws-o.git   
    fetch = +refs/heads/*:refs/remotes/Codaset/*    
[remote "Paws"]   
    url = git@github.com:Paws/Paws.o.git    
    fetch = +refs/heads/*:refs/remotes/Paws/*   
to create a merged‐remote for "Paws" and "Codaset", I can add the following after all of those:   

[remote "Origin"]   
    url = git@github.com:Paws/Paws.o.git    
    url = git@codaset.com:elliottcable/paws-o.git

Once I’ve done this, when I git push Origin Master, it will push to both Paws/Master and Codaset/Master sequentially, making life a little easier.

  • ElliotCable (StackOverflow)

Good housekeeping

git gc --aggressive --prune=now

This runs a number of housekeeping tasks within the current repository, such as compressing file revisions (to reduce disk space and increase performance) and removing unreachable objects which may have been created from prior invocations of git add. Users are encouraged to run this task on a regular basis within each repository to maintain good disk space utilization and good operating performance.

To make a new branch

git checkout -b iss53

Switched to a new branch 'iss53'

    git branch iss53  
    git checkout iss53  
    nano index.html  
    git commit -a -m 'added a new footer [issue 53]'  
    git checkout master

Switched to branch 'master'

git checkout -b hotfix  
vim index.html  
git commit -a -m 'fixed the broken email address'   

git checkout master   
git merge hotfix  
git branch -d hotfix  

git checkout iss53  
vim index.html  
git commit -a -m 'finished the new footer [issue 53]'   
git checkout master   
git merge iss53   

git branch -d iss53   
git merge iss53   

git status    

git reflog  

* The reflogs stay until expired (which can be done with the git reflog expire command). The default for unreachable commits is 30 days (or the gc.reflogExpireUnreachable config value) or, for reachable commits, 90 days (or the gc.reflogExpire config value).  

```bash
git checkout 'master@{2014-02-25 18:30:00}'   
git rev-list --before=2014-02-01 master   
git checkout --before=2014-02-01 master   
git checkout 'master@{14 days ago}'   
git reset --hard   
git checkout 'master@{7 days ago}' -- path/to/file.txt  

git checkout HEAD^
git checkout -f master
git rev-parse HEAD # see the sha1 of your current revision
  • 1.minute.ago
  • 1.hour.ago
  • 1.day.ago
  • yesterday
  • 1.week.ago
  • 1.month.ago
  • 1.year.ago
  • 2011-05-17.09:00:00