Introduction
I won't dive into the history of version control or stuff like that. In this article, I aimed to create a quick how-to document for Git. By the way, if you are new to Git, I describe it as 'spaceship over a file system with a time machine'. You can freeze time in any space, you can travel to those frozen points and live again from that point of time. I think I am about to end up with parallel universes and related paradoxes. Still, I want to live in Git.
Background
There exist two important points to keep in mind when using Git.
Three states of a file
- Modified (working on the file in working directory)
- Staged (ready-to-commit in staging area)
- Committed (frozen in repository)
Bold words above are common terminology in Git. Working directory is the git-tracked directory. When you create a file in working directory, it is actually marked as untracked by Git. Your untracked and modified files will never go into the repository unless you take them to the staging area explicitly. After you stage all your work, you can commit them into the repository, which means you freeze the file system at that point of time.
Where is the HEAD?
HEAD is a special pointer in Git system. It can be thought as a pointer to the place where you are about to commit. When you tell Git to commit, HEAD shows the time point to freeze your current space. Always know where your HEAD is while working within Git.
Last point before starting. Remember to visit help when you are in doubt.
$git help <git_command>
- Working with files
- Working with directories
- Commits
- Branching
- Remote repositories
- Stashing
Using Git
Start a new repository in the current directory || to_content
$ git init
Initialized empty Git repository in /cygdrive/d/projects/test/.git/
### 'status' command shows the current state of your work
### and mostly tells you how to proceed.
### in this case, there is nothing to commit and it tells you that you
### can use 'add' command to track a file.
$ git status
# On branch master
#
# Initial commit
#
nothing to commit (create/copy files and use "git add" to track)
Stage a file (prepare for commit) || to_content
### create a file
$ touch 1.c
### see what happens
$ git status
# On branch master
#
# Initial commit
#
# Untracked files:
# (use "git add <file>..." to include in what will be committed)
#
# 1.c
nothing added to commit but untracked files present (use "git add" to track)
### we have an untracked file, and we can track it by using 'add' command as
### it says
$ git add 1.c
### check status
$ git status
# On branch master
#
# Initial commit
#
# Changes to be committed:
# (use "git rm --cached <file>..." to unstage)
#
# new file: 1.c
#
### 1.c is now staged (can be committed into the repo).
### if you like, you can take it out of the staging area (which makes it untracked)
### by using 'rm --cached' command as it says.
Commit changes (create a time point to jump later) || to_content
### commit the staged files with a commit note
$ git commit -m "first file added"
[master (root-commit) 55b349c] first file added
0 files changed, 0 insertions(+), 0 deletions(-)
create mode 100644 1.c
### see the status
$ git status
# On branch master
nothing to commit (working directory clean)
Remove a file || to_content
### 'rm' command does two things:
### 1- removes file from working directory,
### 2- stages this change (makes ready to commit)
$ git rm 1.c
rm '1.c'
$ git status
# On branch master
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
#
# deleted: 1.c
#
Take back this delete || to_content
### reset HEAD for this file (unstage this change)
$ git reset HEAD 1.c
Unstaged changes after reset:
D 1.c
### now this change is not staged.
$ git status
# On branch master
# Changes not staged for commit:
# (use "git add/rm <file>..." to update what will be committed)
# (use "git checkout -- <file>..." to discard changes in working directory)
#
# deleted: 1.c
#
no changes added to commit (use "git add" and/or "git commit -a")
### call back 1.c from the last commit point to the working directory
$ git checkout 1.c
$ git status
# On branch master
nothing to commit (working directory clean)
Add a file to ignore list || to_content
### create a file
$ touch 2.out
### create '.gitignore' special file
### this file shows which patterns will not be tracked by Git.
$ echo .gitignore > .gitignore
$ echo 2.out >> .gitignore
### git doesn't see '2.out' anymore
$ git status
# On branch master
nothing to commit (working directory clean)
Rename a file || to_content
### use 'mv' command
$ git mv 1.c 2.c
$ git status
# On branch master
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
#
# renamed: 1.c -> 2.c
#
Add changes to the last commit (in case of you forget some simple things) || to_content
### create some files
$ touch 2.c 3.c
### add them to the staging area
$ git add .
$ git status
# On branch master
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
#
# new file: 2.c
# new file: 3.c
#
### commit changes
$ git commit -m "new files added"
[master 830d12c] new files added
0 files changed, 0 insertions(+), 0 deletions(-)
create mode 100644 2.c
create mode 100644 3.c
### oops, forgotten comments in 1.c
$ echo aa > 1.c
### 1.c is modified
$ git status
# On branch master
# Changes not staged for commit:
# (use "git add <file>..." to update what will be committed)
# (use "git checkout -- <file>..." to discard changes in working directory)
#
# modified: 1.c
#
no changes added to commit (use "git add" and/or "git commit -a")
### add last changes to the staging area
$ git add .
### 'commit --amend' to append those changes to the last commit
$ git commit --amend
[master d1941e8] new files added
1 files changed, 1 insertions(+), 0 deletions(-)
create mode 100644 2.c
create mode 100644 3.c
Adding a directory and a file || to_content
### create a directory and a file in it
$ mkdir dir1
$ touch dir1/11.c
### see status
$ git status
# On branch master
# Untracked files:
# (use "git add <file>..." to include in what will be committed)
#
# dir1/
nothing added to commit but untracked files present (use "git add" to track)
### add changes to the staging area
$ git add .
$ git status
# On branch master
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
#
# new file: dir1/11.c
#
### commit changes
$ git commit -m "dir1 added"
[master bc39a14] dir1 added
0 files changed, 0 insertions(+), 0 deletions(-)
create mode 100644 dir1/11.c
Delete a directory || to_content
$ git rm -r dir1
rm 'dir1/11.c'
$ git status
# On branch master
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
#
# deleted: dir1/11.c
#
Undo it || to_content
$ git reset HEAD dir1
Unstaged changes after reset:
D dir1/11.c
$ git checkout dir1
$ git status
# On branch master
nothing to commit (working directory clean)
Rename a directory || to_content
$ git mv dir1 dir2
$ git status
# On branch master
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
#
# renamed: dir1/11.c -> dir2/11.c
#
Add a directory to ignore list || to_content
$ mkdir dir2
$ touch dir2/21.c
### caution: adding 'dir2/' makes a recursive description.
### all 'dir2/'s will be ignored in every directory.
$ echo "dir2/" >> .gitignore
$ git status
# On branch master
nothing to commit (working directory clean)
See commit history || to_content
### every commit is pointed by its checksum calculated over some statistics of that commit.
### checksum has 40 hex chars, output of SHA-1 algorithm
$ git log
commit d1941e8a7f76067c4ea300d10ca6ad18fa8f6264
Author: ozanoner
Date: Mon Mar 31 21:02:59 2014 +0300
new files added
commit 55b349ca5142282124bdef0ebb8cf9b46e1bb96f
Author: ozanoner
Date: Mon Mar 31 20:39:40 2014 +0300
first file added
Tagging commits || to_content
### list commits one-line, reverse ordered by its date
$ git log --pretty=oneline
d1941e8a7f76067c4ea300d10ca6ad18fa8f6264 new files added
55b349ca5142282124bdef0ebb8cf9b46e1bb96f first file added
### tag a commit
$ git tag v0.1 55b349ca5142282124bdef0ebb8cf9b46e1bb96f
### tag latest commit
$ git tag v0.2
### list tags
$ git tag
v0.1
v0.2
### list tags and commit messages
$ git tag -n
v0.1 first file added
v0.2 new files added
Show commit with its tag || to_content
### shows commit (checksum, author, date, message, changes) tagged as 'v0.2'
$ git show v0.2
commit d1941e8a7f76067c4ea300d10ca6ad18fa8f6264
Author: ozanoner
Date: Mon Mar 31 21:02:59 2014 +0300
new files added
diff --git a/1.c b/1.c
index e69de29..e61ef7b 100644
--- a/1.c
+++ b/1.c
@@ -0,0 +1 @@
+aa
diff --git a/2.c b/2.c
new file mode 100644
index 0000000..e69de29
diff --git a/3.c b/3.c
new file mode 100644
index 0000000..e69de29
Delete a tag || to_content
### delete tag v0.2 (nothing with commit)
$ git tag -d v0.2
Deleted tag 'v0.2' (was d1941e8)
### list tags with commit messages
$ git tag -n
v0.1 first file added
Create a branch and work on it || to_content
### create a new branch named 'test_branch' from the current branch
$ git branch test_branch
### make it active branch
### HEAD is on 'test_branch' now
$ git checkout test_branch
Switched to branch 'test_branch'
### edit 1.c version in 'test_branch'
$ echo bb >> 1.c
### add changes to the staging area and commit them ('commit -a')
$ git commit -am '1.c edited in new branch'
### show branches
$ git branch -v
master f694fb8 first commit
* test_branch 44e91ae 1.c edited in new branch
Merge to main branch ('master') and delete temporary branch ('test_branch') || to_content
### make 'master' active branch (ie. HEAD moved to 'test_branch')
$ git checkout master
Switched to branch 'master'
### merge 'test_branch' onto 'master'
$ git merge test_branch
Updating f694fb8..44e91ae
Fast-forward
1.c | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)
### check logs to see what happened
$ git log
commit 44e91aea6ee69b874e1cbb2e73390fb5e0eb68bb
Author: ozanoner
Date: Wed Apr 2 15:34:28 2014 +0300
1.c edited in new branch
commit f694fb8f1c30c9564be9a8bf32392dc84b4559a8
Author: ozanoner
Date: Wed Apr 2 15:32:14 2014 +0300
first commit
$ git status
# On branch master
nothing to commit (working directory clean)
### we are done with 'test_branch'. delete it
$ git branch -d test_branch
Deleted branch test_branch (was 44e91ae).
Find difference between branches || to_content
### create 'new_dev' and move HEAD to it.
$ git checkout -b new_dev
Switched to a new branch 'new_dev'
### edit 1.c in 'new_dev'
$ echo dd >> 1.c
### stage and commit
$ git commit -am 'modified in new_dev'
[new_dev 385f6a9] modified in new_dev
1 files changed, 1 insertions(+), 0 deletions(-)
### move HEAD to 'master' branch
$ git checkout master
Switched to branch 'master'
### compare 'new_dev' and the current branch ('master')
$ git diff new_dev
diff --git a/1.c b/1.c
index 955bebf..3b7dd8b 100644
--- a/1.c
+++ b/1.c
@@ -1,4 +1,3 @@
aa
bb
cc
-dd
### compare file versions on different branches
$ git diff master:1.c new_dev:1.c
diff --git a/master:1.c b/new_dev:1.c
index 3b7dd8b..955bebf 100644
--- a/master:1.c
+++ b/new_dev:1.c
@@ -1,3 +1,4 @@
aa
bb
cc
+dd
Another difference example || to_content
### edit 2.c in 'master'
$ echo aa > 2.c
### and stage changes
$ git add .
### this change is included in comparison since it is in the staging area.
$ git diff new_dev
diff --git a/1.c b/1.c
index 955bebf..3b7dd8b 100644
--- a/1.c
+++ b/1.c
@@ -1,4 +1,3 @@
aa
bb
cc
-dd
diff --git a/2.c b/2.c
new file mode 100644
index 0000000..e61ef7b
--- /dev/null
+++ b/2.c
@@ -0,0 +1 @@
+aa
### change to 2.c is not visible by the latest commit in branch 'master'
$ git diff new_dev master
diff --git a/1.c b/1.c
index 955bebf..3b7dd8b 100644
--- a/1.c
+++ b/1.c
@@ -1,4 +1,3 @@
aa
bb
cc
-dd
### merge 'master' and 'new_dev'
$ git merge new_dev
Updating 97d650c..385f6a9
Fast-forward
1.c | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)
### no difference between 'master' and 'new_dev'
$ git diff master new_dev
### delete 'new_dev' branch
$ git branch -d new_dev
Deleted branch new_dev (was 385f6a9).
Rebasing (appending last work from a different branch) || to_content
### create and switch to 'testing' branch
$ git checkout -b testing
Switched to a new branch 'testing'
### edit 1.c in 'testing'
$ echo ccc >> 1.c
### stage and commit
$ git commit -am '1.c corrected'
[testing 0c8e0a2] 1.c corrected
1 files changed, 1 insertions(+), 0 deletions(-)
### append it to 'master'
$ git rebase master
Current branch testing is up to date.
### switch to 'master'
$ git checkout master
Switched to branch 'master'
### this 'merge' command just re-aligns 'master'
$ git merge testing
Updating 1d5b72e..0c8e0a2
Fast-forward
1.c | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)
$ cat 1.c
aa
bb
ccc
### delete 'testing' branch
$ git branch -d testing
Deleted branch testing (was 0c8e0a2)
Clone a remote repository || to_content
### clone remote repository in the current directory.
### that means remote repo is duplicated in local directory as 'master' branch.
### note that another branch created as 'origin/master' in local repo
### representing remote branch
$ git clone https:
Cloning into '.'...
remote: Counting objects: 5, done.
remote: Compressing objects: 100% (2/2), done.
remote: Total 5 (delta 0), reused 3 (delta 0)
Unpacking objects: 100% (5/5), done.
### see log for this new repo
$ git log
commit 44a94d529c9be2920e62400ee570ebdb23c101fd
Author: ozanoner
Date: Tue Apr 1 15:15:01 2014 +0300
Delete README.txt
commit 4cf94f8556d45e258cc127b891c1a6add1f1617c
Author: ozanoner
Date: Tue Apr 1 15:13:44 2014 +0300
first commit
Fetch from remote repo (refresh origin/master || to_content
### list remote repos
$ git remote -v
origin https:
origin https:
### fetch from remote repo into local representation (origin/master)
$ git fetch origin
remote: Counting objects: 4, done.
remote: Total 3 (delta 0), reused 0 (delta 0)
Unpacking objects: 100% (3/3), done.
From https:
44a94d5..1ea2bab master -> origin/master
### no change in 'master' yet
$ git log
commit 44a94d529c9be2920e62400ee570ebdb23c101fd
Author: ozanoner
Date: Tue Apr 1 15:15:01 2014 +0300
Delete README.txt
commit 4cf94f8556d45e258cc127b891c1a6add1f1617c
Author: ozanoner
Date: Tue Apr 1 15:13:44 2014 +0300
first commit
### merge 'master' and 'origin/master'
$ git merge origin/master
Updating 44a94d5..1ea2bab
Fast-forward
README.md | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)
create mode 100644 README.md
### changes in remote repo is now merged into 'master'
### README.md file is added.
$ git log
commit 1ea2babd342e1432626d6536afbcce320005b643
Author: ozanoner
Date: Thu Apr 3 10:39:09 2014 +0300
Create README.md
commit 44a94d529c9be2920e62400ee570ebdb23c101fd
Author: ozanoner
Date: Tue Apr 1 15:15:01 2014 +0300
Delete README.txt
commit 4cf94f8556d45e258cc127b891c1a6add1f1617c
Author: ozanoner
Date: Tue Apr 1 15:13:44 2014 +0300
first commit
Pull from remote (fetch into 'origin/master' and merge onto 'master') || to_content
### pull command (fetch&merge)
$ git pull origin
remote: Counting objects: 4, done.
remote: Compressing objects: 100% (2/2), done.
remote: Total 3 (delta 0), reused 0 (delta 0)
Unpacking objects: 100% (3/3), done.
From https:
1ea2bab..b456638 master -> origin/master
Updating 1ea2bab..b456638
Fast-forward
1.c | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)
create mode 100644 1.c
### see last 2 logs
$ git log -2
commit b456638c54a61595c1f112cdb13ac5574aaba58c
Author: ozanoner
Date: Thu Apr 3 10:43:30 2014 +0300
Create 1.c
commit 1ea2babd342e1432626d6536afbcce320005b643
Author: ozanoner
Date: Thu Apr 3 10:39:09 2014 +0300
Create README.md
Push to remote (send changes to remote repository) || to_content
### create a file and commit changes
$ touch 2.c
$ git commit -am '2.c added'
[master 50b88d7] 2.c added
0 files changed, 0 insertions(+), 0 deletions(-)
create mode 100644 2.c
### push changes to remote 'origin'
### as from local 'master' branch to remote 'master' branch
$ git push origin master:master
Username for 'https://github.com':
Password for 'https://ozanoner@github.com':
Counting objects: 4, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 289 bytes, done.
Total 3 (delta 0), reused 0 (delta 0)
To https:
b456638..50b88d7 master -> master
Push to a remote branch || to_content
### create and switch to branch 'testing'
$ git checkout -b testing
Switched to a new branch 'testing'
### create a file and commit changes
$ echo aa > 2.c
$ git commit -am 'testing 2.c'
[testing 7be7133] testing 2.c
1 files changed, 1 insertions(+), 0 deletions(-)
### push changes to remote 'origin'
### from local branch 'testing' to remote branch 'testing'
$ git push origin testing:testing
Username for 'https://github.com':
Password for 'https://ozanoner@github.com':
Counting objects: 3, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (2/2), done.
Writing objects: 100% (2/2), 219 bytes, done.
Total 2 (delta 1), reused 0 (delta 0)
To https:
50b88d7..7be7133 testing -> testing
Find difference with a remote repo || to_content
### first fetch into local 'origin/master' branch
$ git fetch origin
remote: Counting objects: 1, done.
remote: Total 1 (delta 0), reused 0 (delta 0)
Unpacking objects: 100% (1/1), done.
From https:
50b88d7..b26e2af master -> origin/master
### then see the difference
$ git diff origin
diff --git a/2.c b/2.c
index e61ef7b..e69de29 100644
--- a/2.c
+++ b/2.c
@@ -1 +0,0 @@
-aa
### create a branch (dont switch yet)
$ git branch testing
### modify file in the current branch
$ echo cc >> 1.c
$ git status
# On branch master
# Changes not staged for commit:
# (use "git add <file>..." to update what will be committed)
# (use "git checkout -- <file>..." to discard changes in working directory)
#
# modified: 1.c
#
no changes added to commit (use "git add" and/or "git commit -a")
### want to switch branch 'testing' but need to save current state without commit
### solution is stashing
$ git stash
Saved working directory and index state WIP on master: e01a00f Update 1.c
HEAD is now at e01a00f Update 1.c
### move HEAD to 'testing' branch
$ git checkout testing
Switched to branch 'testing'
### done with 'testing', switch to 'master'
$ git checkout master
Switched to branch 'master'
### oops, status tells us no change
$ git status
# On branch master
nothing to commit (working directory clean)
### forgotten to apply temporary versions, therefore apply stash
$ git stash apply
# On branch master
# Changes not staged for commit:
# (use "git add <file>..." to update what will be committed)
# (use "git checkout -- <file>..." to discard changes in working directory)
#
# modified: 1.c
#
no changes added to commit (use "git add" and/or "git commit -a")
### done with that stash, drop it
$ git stash drop
Dropped refs/stash@{0} (e62a20cd9ff4053dfcd64e26d038955f2274de54)
|| to_content
References
No need to say but:
https://www.google.com.tr/#q=git+reference+book
and this book contains everything you may need:
http://git-scm.com/book