Mastering Git Basics
Given by @mojombo the cofounder and cto of github.
Initial Config:
git config --global user.name [NAME]
git config --global user.email [EMAIL]
git config --global color.ui true
Last one gives nice colors for diffs and such.
Creating and Committing
Make a dir for your project:
$ cd patch/to/repos
$ mkdir hello
$ cd hello
git init
$ git init # converts empty directory into a git repo. Creates .git dir.
Behold the index
Create file hello with content "echo hello". The index is stored in .git directory
$ git add hello # adds hello.sh to the index in .git
Commit
$ git commit -m "first commit"
Git takes snapshots of index and makes a commit out of them.
$ git log
Shows history of commits.
Status
$ git status
Shows current status of repo. All modified files.
Diff
$ git diff
Shwows difference between index and working directory.
Example after adding and commiting a a file hello and then changing it:
12:28:43 $ git diff
diff --git a/hello b/hello
index 09990d4..953a442 100644
--- a/hello
+++ b/hello
@@ -1 +1 @@
-echo "hello"
+echo "hello 2"
Interactive add:
12:29:12 $ git add -p
diff --git a/hello b/hello
index 09990d4..953a442 100644
--- a/hello
+++ b/hello
@@ -1 +1 @@
-echo "hello"
+echo "hello 2"
Stage this hunk [y,n,q,a,d,/,e,?]?
Will ask for each hunk.
After saying yes we can see the diff is now also in the index, ready for committing.
Now 'git diff' is empty since the diff is in the index. There is no difference between the index and the working direcotry.
What if we want to review whats in the index, but different from first commit?
12:30:54 $ git diff --staged
diff --git a/hello b/hello
index 09990d4..953a442 100644
--- a/hello
+++ b/hello
@@ -1 +1 @@
-echo "hello"
+echo "hello 2"
Now make a second commit.
12:31:38 $ git commit -m "second commit"
[master 6cb636e] second commit
1 files changed, 1 insertions(+), 1 deletions(-)
Remember:
1) make changes to working dir
2) stage these changes to index
3) commit the current stat
Now we have 2 commits. Everything is consitent now. Now changes from index to working dir and no changes from last commit to index.
Every commit keeps record of the parent.
Branching and Merging
12:32:52 $ git branch
* master
Shows the current branch with star and all other branches. master is the default branch.
Branches are just pointers to commits. Thus the master branch is simply pointing to our second commit. This is why branches are so easy in git and powerful.
Easiest to think of the working directory corresponding to a branch.
As you commit the branch moves with you.
Create a new branch:
12:36:19 $ git branch uppercase
12:38:25 $ git branch
* master
uppercase
Both branches point to the same commit and the working directory points still to the master branch.
Switch to a branch:
12:38:34 $ git checkout uppercase
Switched to branch 'uppercase'
12:39:09 $ git branch
master
* uppercase
Now our working directory corresponds to the uppercase branch.
When switching branches it will try to apply anything staged to that new branch -- may conflict.
Note: 'git stash' makes a temp commit to save info for moving branches and can 'git stash apply' later.
Make a change in the new branch and add.
diff --git a/hello b/hello
index 953a442..1ba14ad 100644
--- a/hello
+++ b/hello
@@ -1 +1 @@
-echo "hello 2"
+echo "HELLO 2"
Stage this hunk [y,n,q,a,d,/,e,?]?
Now commit:
12:43:41 $ git commit -m "commit 2"
[uppercase d5e17c4] commit 2
1 files changed, 1 insertions(+), 1 deletions(-)
List commits a branch points to:
12:43:47 $ git branch -v
master 6cb636e second commit
* uppercase d5e17c4 commit 2
Just shows the first 7 chars of commit hash, since usually enough to tell the difference.
Switch back to master and working dir changes:
12:45:28 $ cat hello
echo "HELLO 2"
[tristan@duff:~/mastering-git-basics/hello]
12:45:30 $ git checkout master
Switched to branch 'master'
[tristan@duff:~/mastering-git-basics/hello]
12:45:35 $ cat hello
echo "hello 2"
Started late... Moving to 'reset'
git reset --hard
Dangerous, use with care. Deletes uncommitted changes. Changes branch to point somewhere else from the current commit. If no branch is now pointing to that commit you can use reflog to find the hash of that commmit and get it back, for 30 days.
git reflog
Shows previous values of where HEAD points
12:47:59 $ git reflog
6cb636e HEAD@{0}: checkout: moving from uppercase to master
d5e17c4 HEAD@{1}: commit: commit 2
6cb636e HEAD@{2}: checkout: moving from master to uppercase
6cb636e HEAD@{3}: commit: second commit
d02f69f HEAD@{4}: commit (initial): first commit
git diff two commits
12:51:26 $ git diff master uppercase
diff --git a/hello b/hello
index 953a442..1ba14ad 100644
--- a/hello
+++ b/hello
@@ -1 +1 @@
-echo "hello 2"
+echo "HELLO 2"
git merge
Merging in git is super easy. Lets merge uppercase and master.
12:53:44 $ git merge uppercase
Updating 6cb636e..d5e17c4
Fast forward
hello | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
Changes working directory. This is a fast forward commit since it was a direct descendant of the master's current commit. Simply moves pointer, no real merge needed.
Now both point to same commit.
12:54:51 $ git branch -v
* master d5e17c4 commit 2
uppercase d5e17c4 commit 2
Now we can delete uppercase branch if we don't need it.
12:55:28 $ git branch -d uppercase
Deleted branch uppercase (was d5e17c4).
All that happens is pointer to that commit named uppercase is gone, but no work gone. -d only lets you delete if commits are contained in current history. -D removes even if there are commits not in the history.
What if we have two diverging histories to merge.
Shortcut to create new branch and check it out:
12:56:19 $ git checkout -b greeting
Switched to a new branch 'greeting'
12:58:14 $ git branch -v
* greeting d5e17c4 commit 2
master d5e17c4 commit 2
Lets make some changes to files hello and a new file goodbye.
12:59:11 $ git add -p
diff --git a/hello b/hello
index 1ba14ad..653f53d 100644
--- a/hello
+++ b/hello
@@ -1 +1 @@
-echo "HELLO 2"
+echo "Yo"
Stage this hunk [y,n,q,a,d,/,e,?]? y
12:59:40 $ git add goodbye
12:59:47 $ git commit -m "new greetings"
[greeting 07527ab] new greetings
2 files changed, 3 insertions(+), 1 deletions(-)
create mode 100644 goodbye
13:02:17 $ git checkout master
Switched to branch 'master'
Create README and add 'some great scripts'
[tristan@duff:~/mastering-git-basics/hello]
13:05:49 $ git add .
Adds everything.
Will be making a git cast out of presentation since it was cut short and had to jump around... Will post later.