Git 101

Git Tutorial


Git Basics

Git has three main states that your files can reside in: committed, modified, and staged:

  • Committed means that the data is safely stored in your local database.
  • Modified means that you have changed the file but have not committed it to your database yet.
  • Staged means that you have marked a modified file in its current version to go into your next commit snapshot.

Git States

The basic Git workflow goes something like this:

  1. You modify files in your working tree.
  2. You selectively stage just those changes you want to be part of your next commit, which adds onlythose changes to the staging area.
  3. You do a commit, which takes the files as they are in the staging area and stores that snapshot permanently to your Git directory.

First-Time Git Setup

Your Identity

1
2
git config --global user.name "John Doe"
git config --global user.email johndoe@example.com

GitHub Setup

Connecting over HTTPS doesn't require SSH Keys but you have to type your password every time.

Connecting over SSH requires generating SSH Keys on each computer.

1
2
# create SSH Key for authentication
ssh-keygen -t rsa -C "youremail@example.com"

Then copy the content in id_rsa.pub to GitHub -> Account settings -> Add SSH Key.

1
2
3
4
5
6
7
8
# connect a local repo with github repo
git remote add origin git@github.com:example.git

# first time push -u to connect local branch with server branch
git push -u origin master

# clone a repo from github
git clone git@github.com:example.git

Git Basic Operation

Initializing a Repository in an Existing Directory

1
2
3
4
cd my_project
git init
git add .
git commit -m "message"

Checking Status

1
git status

This will tell you files that are untracked (new file) and tracked but not staged (modified file). git add should be used for both cases. After that git status will show "changes to be committed" and we can use git commit -m "message" to safely commit the change.

A short version:

1
2
3
4
5
6
$ git status -s
M README # modified but not staged
MM Rakefile # both staged and unstaged
A lib/git.rb # new files in staging area
M lib/simplegit.rb # modified and staged
?? LICENSE.txt # new files that aren't tracked

Viewing Changes

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# compared with current saved version
git diff
git diff HEAD

# compare with previous saved version
git diff HEAD~1

# compare stage with current saved version
git diff --staged

# see the difference for a particular file
git diff <file>

# compare between two commits
git diff HEAD~1..HEAD

# compare between two branches
git diff <branch1>..<branch2>

Stashing Files

We can stash our current work and move to another job, say debugging. After finishing the job we can continue on our previous work.

1
2
3
4
5
6
7
8
9
10
11
# stash current work
git stash

# list the stashed work
git stash list

# restore ith stashed work
git stash apply stash@{i} # still keep the stashed content
git stash drop stash@{i} # drop the stashed content

git stash pop stash@{i} # = apply + drop

Committing Your Changes

1
2
3
4
git commit -m "message"

# skipping the staging area
git commit -a -m "message"

Tagging

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# list all the tags
git tag

# list all the tags with particluar pattern
git tag -l "v1.0"

# create a tag on the latest commit
git tag <name>

# create a tag on the previous commit
git tag <name> <commit id>

# create a tag with message
git tag -a <name> -m "meass"

# show information of a specific tag
git show <tag name>

# push a tag to remote
git push origin <tag name>

# push all the tags at once
git push origin --tags

# delete a local tag
git tag -d <tag name>

# delete a remote tag
git tag -d <tag name> # first delete locally
git push origin :refs/tags/<tag name>

Removing Files

Remove the file from both the staging area and the working directory.

1
2
3
4
5
# remove the file from both the staging area and the working directory
git rm

# remove the file from staging area but keep in the working directory
git rm --cached

Renaming Files

1
git mv a.txt b.txt

Git is case insensitive. Use git mv if you want to change the case of the filename.

Ignoring Files

There might be some files that you don't want Git to track, for example, the log file and the file produced by building system. Then you can add a .gitignore file in your folder.

Some examples

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# ignore all .a files
*.a

# but do track lib.a, even though you're ignoring .a files above
!lib.a

# only ignore the TODO file in the current directory, not subdir/TODO
/TODO

# ignore all files in any directory named build
build/

# ignore doc/notes.txt, but not doc/server/arch.txt
doc/*.txt

# ignore all .pdf files in the doc/ directory and any of its subdirectories
doc/**/*.pdf

Viewing the Commit History

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
git log

# show the difference introduced in each commit
git log -p

# show only the latest two entries
git log -p -2

# abbreviated stats
git log --stat

# change output format
git log --pretty=oneline
git log --pretty=short
git log --pretty=full
git log --pretty=fuller

# specify your own output format
git log --pretty=format:"%h - %an, %ar : %s"

# graph
git log --pretty=oneline --graph

# limit output
git log --since=2.weeks
git log --author=silencial
git log --grep=message

# specify changes
git log -S function_name

Undoing Things

Committed Too Early

1
2
3
git commit -m 'initial commit'
git add forgotten_file
git commit --amend

Unstaging a Staged File

1
git reset HEAD <file>

Unmodifying a Modified File

1
git checkout -- <file>

git checkout just use the latest version you committed to replace the one in your working directory, so your can also use this when your delete a file by accident.

Undoing Commits

HEAD is a pointer that points to the current version.

1
2
3
4
5
6
7
8
9
10
11
# version rollback
git reset --hard HEAD^

# return to any commit with commit id
git rest --hard commit_id

# find the logs of history
git log

# find the logs of all (back to future)
git reflog

Working With Remotes

Showing Your Remotes

1
2
3
4
5
6
7
git remote

# show the URLs for reading and writing
git remote -v

# show more information about a particular remote
git remote show <remote>

Adding Remote Repositories

1
2
3
4
5
6
7
8
9
10
11
# give a name other that 'origin'
git remote add <shortname> <url>

# only downloads the data without merging
git fetch <remote>

# fetch & merge
git pull

# push your branch to your remote server
git push <remote> <branch>

Renaming and Removing Remotes

1
2
git remote rename a b
git remote remove a

Git Branching

Creating and Merging Branches

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# view branches
git branch

# create a branch
git branch <name>

# switch to a branch
git checkout <name>
git checkout -b <name> # create and then switch

# merge a branch to current branch
git merge <name>

# delete a branch
git branch -d <name>

Solving Conflicts

When Git can't auto merge two branches, we need to merge the file with conflicts manually.

1
2
3
4
5
# config the merging tool
git config --global merge.tool meld

# merge with tool
git mergetool

Git Aliases

You can also add alias in .gitconfig file.

1
2
3
4
5
# use git unstage
git config --global alias.unstage "reset HEAD --"

# use git last
git config --global alias.last "log -1 HEAD"