Available online at https://bauglir.github.io/me-myself-and-git
Every user has their own copy of the repository
Changes can be shared directly between repositories
The (optional) server copy is not really special
$ git init my-project && cd my-project Initialized empty Git repository in /home/jkraak/Projects/my-project/.git/
$ git clone email@example.com:bauglir/me-myself-and-git.git Cloning into 'me-myself-and-git'... remote: Counting objects: 7127, done. remote: Total 7127 (delta 0), reused 0 (delta 0), pack-reused 7127 Receiving objects: 100% (7127/7127), 5.38 MiB | 2.52 MiB/s, done. Resolving deltas: 100% (3767/3767), done. Checking connectivity... done.
$ echo 'foo' > foo.txt
$ echo 'bar' > bar.txt
$ git status On branch master Initial commit Untracked files: (use "git add < file>..." to include in what will be committed) bar.txt foo.txt nothing added to commit but untracked files present (use "git add" to track)
git status is your friend! It provides hints on what to do next
$ git add foo.txt
$ git status On branch master Initial commit Changes to be committed: (use "git rm --cached < file>..." to unstage) new file: foo.txt new file: bar.txt
$ git commit -m 'Add foo and bar literature' [master (root-commit) 3f91579] Add foo and bar literature 2 files changed, 2 insertions(+) create mode 100644 bar.txt create mode 100644 foo.txt
$ echo 'baz' >> foo.txt
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: foo.txt no changes added to commit (use "git add" and/or "git commit -a")
$ git diff diff --git a/foo.txt b/foo.txt index 257cc56..0c071e1 100644 --- a/foo.txt +++ b/foo.txt @@ -1 +1,2 @@ foo +baz
$ git add -u && git commit -m 'Add baz reference' [master e981856] Add baz reference 1 file changed, 1 insertion(+)
$ git log commit e9818560edc7f0cf41317f15eec28167e507a3f7 Author: Joris Kraak < firstname.lastname@example.org> Date: Tue Feb 24 12:20:25 2015 +0100 Add baz reference commit 3f91579623ef93cde0ebf5300b6da99bd70fa835 Author: Joris Kraak < email@example.com> Date: Tue Feb 24 12:08:31 2015 +0100 Add foo and bar literature
$ git rm * rm 'bar.txt' rm 'foo.txt'
$ git status On branch master Changes to be committed: (use "git reset HEAD < file>..." to unstage) deleted: bar.txt deleted: foo.txt
$ git reset HEAD foo.txt Unstaged changes after reset: D foo.txt
$ git status On branch master Changes to be committed: (use "git reset HEAD < file>..." to unstage) deleted: bar.txt 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: foo.txt
$ git checkout -- foo.txt
On branch master Changes to be committed: (use "git reset HEAD < file>..." to unstage) deleted: bar.txt
$ ls foo.txt
Branches make it easier to collaborate on a shared code base
What made Git easy for me is visualizing everything as a tree
$ git log --graph --oneline --decorate --all
or get a GUI capable of showing the history formatted as a tree
Git is very flexible with regards to picking a workflow
Popular choices are:
Keep a single master branch
Implement new features/bug fixes taking more than a single commit on a separate branch, then merge into master
Before merging, 'rebase' feature branch on master and fix any conflicts that may arise
Make the merge back into master explicit by forcing a merge commit
git merge --no-ff
This results in a very clean history where the work on features stays clearly visible after a mergehttp://mislav.uniqpath.com/2013/02/merge-vs-rebase/
Let's force two branches to diverge
$ git checkout -b my-branch Switched to a new branch 'my-branch'
$ cp foo.txt quuz.txt $ git add quuz.txt && git commit -m 'Add quuz literature' [my-branch cb4c59e] Add quuz literature 1 file changed, 2 insertions(+) create mode 100644 quuz.txt
$ git checkout master Switched to branch 'master'
$ cp foo.txt quux.txt $ git add quux.txt && git commit -m 'Add quux literature' [master afda51f] Add quux literature 1 file changed, 2 insertions(+) create mode 100644 quux.txt
$ git checkout my-branch Switched to branch 'my-branch'
'my-branch' does not yet contain the quux literature
$ ls bar.txt foo.txt quuz.txt
Take 'my-branch' and attach it to the new top of the tree
$ git rebase master my-branch First, rewinding head to replay your work on top of it... Applying: Add quuz literature
$ ls bar.txt foo.txt quux.txt quuz.txt
Finally merge 'my-branch' into 'master'
$ git checkout master Switched to branch 'master' $ git merge --no-ff my-branch -m 'Merge branch my-branch' Merge made by the 'recursive' strategy. quuz.txt | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 quuz.txt
* f08e76f (HEAD, master) Merge branch my-branch |\ | * 29233b8 (my-branch) Add quuz literature |/ * afda51f Add quux literature * e981856 Add baz reference * 3f91579 Add foo and bar literature
Work can be shared using 'remotes'
The 'server' is typically referred to as 'origin'
When cloning a repository, the 'origin' is automatically set
First create a 'server' repository
$ git init --bare server
Then add the 'server' as a remote
$ git remote add origin server
Verify the remotes of the current repository
$ git remote -v origin server (fetch) origin server (push)
Publish our local work
$ git push origin master
* deadbeef (origin/foo) Remote only work | * f08e76f (HEAD, master, origin/master) Merge branch my-branch | |\ | | * 29233b8 (my-branch) Add quuz literature | |/ |/ * afda51f Add quux literature * e981856 Add baz reference * 3f91579 Add foo and bar literature
git fetch remote_name branch_name synchronizes local
branch history with remote
git pull remote_name branch_name fetches and merges
or rebases a local branch with its remote equivalent
git push remote_name branch_name publishes local
history to remote repository
Websites hosting Git repositories
Provide online functionality for branching and merging (Pull Requests)
Issue tracking capable of linking to code
Typically used as the 'server'
Git typically communicates over SSH
SSH requires public/private key pairs
These have to be in openSSH format
The private key should be password protected and kept safe
The public key can be distributed where necessary
To cache the private key password, solutions such as Pageant can be used
git commit --amend
-pto most operations allows more granular control (i.e. within files)
git config --global alias.graph 'log --graph --oneline --decorate --all'
git stash) allows temporary storage of in-progress work, useful when rebasing
git push -u remote_name branch_name'tracks' remote branches
git config --global url.https://.insteadOf git://
git config --global color.ui trueforces pretty colors
git config --global pull.rebase trueforces a pull to always 'rebase' instead of 'merge'
rebase, etc. have a