Serverside Webscripting [JLW384]

xx.git

Intro

What you guys think of it

What I think of it

What is Git?

Git is a free and open source distributed version control system designed to handle everything from small to very large projects with speed and efficiency.
  • Version control system
    • Tell it to keep track of certain files
    • Save the state of files in a historical timeline (repository)
  • Distributed
    • Works offline
    • Several users have their own separate file history
      • These can later on be merged

Installation & Basic Configuration

  • Download the Git binary from git-scm.com
    • On Windows, choose “Run Git and included Linux tools from the Windows Command Prompt” during installation
  • Once installed, tell Git who you are
    $ git config --global user.name "Lorem Ipsum"
    $ git config --global user.email lorem@ips.um
  • Let's also ask for colors while we're at it
    $ git config --global color.ui true

Git GUIs

  • Git is shipped with some (very) basic GUI tools
    • gitk, git-gui
  • Other Git GUIs also exist
Whilst these GUIs are a nice addition, we'll focus on the command line

Getting started

Thank you, thank you. Let's get started. Max, play me over.
(gasps) Looks like someone forgot to feed Max!

Creating a repository

  • Start tracking files in a directory with git init
    bramus in ~/ikdoeict/git-demo
    $ git init
    Initialized empty Git repository in /Users/bramus/Kaho/git-demo/.git/
    
    bramus in ~/ikdoeict/git-demo
    $ 
    • Git automatically creates a (hidden) .git folder containing
      • Meta information
      • The entire history

Checking the status of a repository

  • Git knows whenever a file has changed in the repository
  • Use git status to check
    bramus in ~/ikdoeict/git-demo
    $ touch test.txt
    
    bramus in ~/ikdoeict/git-demo
    $ git status
    
    # …
    #
    # Untracked files:
    # …
    #	test.txt
    #
    
    bramus in ~/ikdoeict/git-demo
    $ 
  • Git compares the current state of the working directory to the last state stored in the history

Staging & committing

  • To save the changes into the history timeline
    1. Select which files you want to save using git addstaging
    2. Actually save them using git commitcommitting
    bramus in ~/ikdoeict/git-demo
    $ git add test.txt
    
    bramus in ~/ikdoeict/git-demo
    $ git commit -m 'Start tracking test.txt'
    [master (root-commit) 9c43f96] Start tracking test.txt
     0 files changed
     create mode 100644 test.txt
    
    bramus in ~/ikdoeict/git-demo
    $ 
  • The current state (actually: a delta) of test.txt is stored in the repository
    • The commit is identified as 9c43f96

Flow visualization

Visual representation of staging and committing in Git

Committing (1)

  • Only staged files are committed
    bramus in ~/ikdoeict/git-demo on master
    $ touch test2.txt
    
    bramus in ~/ikdoeict/git-demo on master
    $ echo 'hello' >> test.txt
    
    bramus in ~/ikdoeict/git-demo on master*
    $ git status
    # On branch master
    # Changes not staged for commit:
    # …
    #	modified:   test.txt
    #
    # Untracked files:
    # …
    #	test2.txt
    #
    bramus in ~/ikdoeict/git-demo on master*
    $ git add test2.txt
    
    bramus in ~/ikdoeict/git-demo on master*
    $ git status
    # On branch master
    # Changes to be committed:
    # …
    #	new file:   test2.txt
    #
    # Changes not staged for commit:
    # …
    #	modified:   test.txt
    #
    
    bramus in ~/ikdoeict/git-demo on master*
    $ git commit -m 'Start tracking test2'
    [master f1c6883] Start tracking test2
     0 files changed
     create mode 100644 test2.txt
    
    bramus in ~/ikdoeict/git-demo on master*
    $ git status
    # On branch master
    # Changes not staged for commit:
    # …
    #	modified:   test.txt
    #
    
    bramus in ~/ikdoeict/git-demo on master*
    $ 

Committing (2)

  • Stage all files + commit them in one command
    $ git commit -am 'commitmessage'
  • Don't create an extra commit when something was forgotten but amend it
    $ git commit --amend -m 'commitmessage'
  • Write good commit messages
    • English
    • Present tense
  • One commit = one set of changes
    • Don't commit 2 features/bugfixes/etc at once

Staging & Unstaging (1)

  • Stage all files
    $ git add .
  • Stage all .txt files
    $ git add *.txt
  • Stage an entire subfolder
    $ git add subfolder/
  • Unstage files
    $ git reset filename

Visualization

Visual representation of staging, unstaging and committing in Git

Staging & Unstaging (2)

  • Deletions are not staged by default
    bramus in ~/ikdoeict/git-demo on master
    $ rm test2.txt
    
    bramus in ~/ikdoeict/git-demo on master
    $ git status
    # On branch master
    # Changes not staged for commit:
    #
    #	modified:   test.txt
    #	deleted:    test2.txt
    #
    
    bramus in ~/ikdoeict/git-demo on master*
    $ git add .
    
    bramus in ~/ikdoeict/git-demo on master*
    $ git status
    # On branch master
    # Changes to be committed:
    # …
    #	modified:   test.txt
    #
    # Changes not staged for commit:
    # …
    #	deleted:    test2.txt
    #
    
    bramus in ~/ikdoeict/git-demo on master*
    $ git add -u .
    
    bramus in ~/ikdoeict/git-demo on master*
    $ git status
    # On branch master
    # Changes to be committed:
    # …
    #	modified:   test.txt
    #	deleted:    test2.txt
    #
    #
    
    bramus in ~/ikdoeict/git-demo on master*
    $ git reset test.txt
    Unstaged changes after reset:
    M	test.txt
    
    bramus in ~/ikdoeict/git-demo on master*
    $ git commit -m 'Deleted test2.txt'
    [master 1d7a184] Deleted test2.txt
     0 files changed
     delete mode 100644 test2.txt
    
    bramus in ~/ikdoeict/git-demo on master*
    $ git status
    # On branch master
    # Changes not staged for commit:
    # …
    #	modified:   test.txt
    #
    #
    
    bramus in ~/ikdoeict/git-demo on master*
    $ ls
    drwxr-xr-x   4 bramus  staff  136 Mar 19 21:18 .
    drwxr-xr-x  10 bramus  staff  340 Mar 19 15:49 ..
    drwxr-xr-x  13 bramus  staff  442 Mar 19 21:24 .git
    -rw-r--r--   1 bramus  staff    6 Mar 19 20:44 test.txt
    
    bramus in ~/ikdoeict/git-demo on master*
    $ git commit -am 'Hello'
    [master c53f9b6] Hello
     1 file changed, 1 insertion(+)
    
    bramus in ~/ikdoeict/git-demo on master
    $ 
  • Solution: use git add -u
  • Git provides a shorthand git rm file

Checking changes (1)

  • Use git diff file to compare the current state with the previously committed state
    bramus in ~/ikdoeict/git-demo on master
    $ echo 'more hello' >> test.txt
    
    bramus in ~/ikdoeict/git-demo on master*
    $ git diff test.txt
    diff --git a/test.txt b/test.txt
    index ce01362..3477282 100644
    --- a/test.txt
    +++ b/test.txt
    @@ -1 +1,2 @@
    hello
    +more hello
    
    bramus in ~/ikdoeict/git-demo on master*
    $ 

Checking changes (2)

Recommended Sublime Text 2 Plugin: GitGutter

Checking the history (1)

  • Use git log to see the commit log
    bramus in ~/ikdoeict/git-demo
    $ git log
    commit c53f9b6bd0e7271af7c5d856f84f51d9b749d77f
    Author: Bramus <bramus@bram.us>
    Date:   Tue Mar 19 22:09:32 2013 +0100
    
        Hello
    
    commit 1d7a18481b5f6664d2cf30b1455c6ad1c041caa2
    Author: Bramus <bramus@bram.us>
    Date:   Tue Mar 19 21:24:13 2013 +0100
    
        Deleted test2.txt
    
    commit f1c68836b8c1f91c16d4f4c0540fca0f251ff946
    Author: Bramus <bramus@bram.us>
    Date:   Tue Mar 19 20:44:31 2013 +0100
    
        Start tracking test2
    
    commit 9c43f961b1defcc2f4f14526a2b20c4f3c267a62
    Author: Bramus <bramus@bram.us>
    Date:   Tue Mar 19 16:02:03 2013 +0100
    
        Start tracking test.txt
    
    bramus in ~/ikdoeict/git-demo
    $ 
    • Press q to exit the commit log

Checking the history (2)

  • Use git log --oneline to get a concise output
    bramus in ~/ikdoeict/git-demo
    $ git log --oneline
    c53f9b6 Hello
    1d7a184 deleted test2.txt
    f1c6883 Start tracking test2
    9c43f96 Start tracking test.txt
    
    bramus in ~/ikdoeict/git-demo
    $ 
  • Filter commits by author
    $ git log --author=name
  • Filter commits in time
    $ git log --since="1 week ago"

Checking the history (3)

  • Ultimate git log
    $ git log --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit
    bramus in ~/ikdoeict/git-demo
    $ git log --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit
    * c53f9b6 - (HEAD, master) Hello (16 minutes ago) <Bramus>
    * 1d7a184 - Deleted test2.txt (61 minutes ago) <Bramus>
    * f1c6883 - Start tracking test2 (2 hours ago) <Bramus>
    * 9c43f96 - Start tracking test.txt (6 hours ago) <Bramus>
    
    bramus in ~/ikdoeict/git-demo
    $ 
    • Pro tip: create an alias git lg for it
      $ git config --global alias.lg "log --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit"
      • From now on, use git lg to get the output as shown above

Git basics summary

  • Create repository
    $ git init
  • Stage file
    $ git add file
  • Unstage file
    $ git reset file
  • Commit staged changes
    $ git commit -m 'message'
  • Check differences in a file (compared to repository)
    $ git diff file
  • Check commit log (using our alias)
    $ git lg

Git basics summary

Don't lose your HEAD!

Welcome to the Head Museum. I'm Leonard Nimoy.

Commit history

  • The entire commit history can be visualized as a timeline
  • Such a timeline is called a branch
    • More than one branch can exist (see further)
    • The default branch is called the master

HEAD

  • The HEAD is a pointer pointing towards the currently checked out (= active) revision (= commit)

Moving the HEAD

  • The HEAD can be moved by checking out a revision
    bramus in ~/ikdoeict/git-demo on master
    $ git lg
    * c53f9b6 - (HEAD, master) Hello (15 hours ago) <Bramus>
    * 1d7a184 - Deleted test2.txt (16 hours ago) <Bramus>
    * f1c6883 - Start tracking test2 (17 hours ago) <Bramus>
    * 9c43f96 - Start tracking test.txt (22 hours ago) <Bramus>
    
    bramus in ~/ikdoeict/git-demo on master
    $ git checkout 1d7a184
    Note: checking out '1d7a184'.
    
    You are in 'detached HEAD' state. You can look around, make experimental
    changes and commit them, and you can discard any commits you make in this
    state without impacting any branches by performing another checkout.
    
    HEAD is now at 1d7a184... Deleted test2.txt
    
    bramus in ~/ikdoeict/git-demo on (no branch)
    $ git lg
    * 1d7a184 - (HEAD) Deleted test2.txt (16 hours ago) <Bramus>
    * f1c6883 - Start tracking test2 (17 hours ago) <Bramus>
    * 9c43f96 - Start tracking test.txt (22 hours ago) <Bramus>
    
    bramus in ~/ikdoeict/git-demo on master
    $ git checkout f1c6883
    Previous HEAD position was 1d7a184... Deleted test2.txt
    HEAD is now at f1c6883... Start tracking test2
    
    bramus in ~/ikdoeict/git-demo on (no branch)
    $ git lg
    * f1c6883 - (HEAD) Start tracking test2 (17 hours ago) <Bramus>
    * 9c43f96 - Start tracking test.txt (22 hours ago) <Bramus>
    
    bramus in ~/ikdoeict/git-demo on master
    $  git checkout master
    Previous HEAD position was f1c6883... Start tracking test2
    Switched to branch 'master'
    
    bramus in ~/ikdoeict/git-demo on master
    $ git lg
    * c53f9b6 - (HEAD, master) Hello (15 hours ago) <Bramus>
    * 1d7a184 - Deleted test2.txt (16 hours ago) <Bramus>
    * f1c6883 - Start tracking test2 (17 hours ago) <Bramus>
    * 9c43f96 - Start tracking test.txt (22 hours ago) <Bramus>
    
    bramus in ~/ikdoeict/git-demo on master
    $ 
    • When checking out a revision the files in your working directory change to the state of the selected revision

Visualization



Visual representation of moving the HEAD using git checkout

Unstaging revisited

  • Unstage one file
    $ git reset filename
  • Unstage all files
    $ git reset HEAD

Discarding changes

  • Unstaged changes can be discarded
    $ git checkout -- filename
    • The selected file will go back to the last committed state
  • Unstage all + discard all changes
    $ git reset HEAD --hard
    • The entire working directory will go back to the last committed state
    • Cannot be undone (!!)
  • Unstage all + stash all changes
    $ git stash
    • The entire working directory will go back to the last committed state
    • Can be undone as the state is saved in a stash

Remotes

Well, let's at least throw this TV away,
the batteries in the remote are gettin' low.

Remotes

  • A repository can be synched with a server
    • In Git this is called a remote
    • A remote is identified by a name, defaulting to origin, and a URL
    • Keep a local copy in sync with the remote by pushing and pulling
    • Several users can push/pull to/from the same remote
    • Possible to define more than one remote (distributed)
  • Visualization

Visual representation of a Git remote

Setting up shop (1)

  • If a local copy of a repository doesn't exist yet
    • Clone the repository locally using git clone url
    • A local copy of the master + the entire commit history is created
    bramus in ~/ikdoeict
    $ git clone git@github.com:fabpot/Silex.git
    Cloning into 'Silex'...
    remote: Counting objects: 6612, done.
    remote: Compressing objects: 100% (1908/1908), done.
    remote: Total 6612 (delta 4225), reused 6317 (delta 4008)
    Receiving objects: 100% (6612/6612), 1.28 MiB | 176 KiB/s, done.
    Resolving deltas: 100% (4225/4225), done.
    
    bramus in ~/ikdoeict
    $ cd Silex
    
    bramus in ~/ikdoeict/Silex on master
    $ git log --oneline
    59e7dbd merged branch davedevelopment/add-doc-info-to-docs (PR #647)
    6a4fffe Added a note about writing documentation
    8e6d30a merged branch davedevelopment/form-extension-points (PR #553)
    7c38c9a Add services allowing for form type extensions and guessers
    fd3ba62 merged branch GromNaN/remember-me (PR #645)
    adc172b Add support for remember-me with RememberMeServiceProvider
    fcd93b3 added a note about all possible options for the session (refs #633)
    a31…bramus in ~/ikdoeict/Silex on master
    $ 
    • Clone a repo in the current directory using git clone url .

Setting up shop (2)

  • If a local copy of a repository already exists
    • Tell the repo where to find the remote: git remote add name url
    • If the remote repository is empty, push your master to it
    bramus in ~/ikdoeict/git-demo on master
    $ git remote add origin git@github.com:bramus/git-demo.git
    
    bramus in ~/ikdoeict/git-demo on master
    $ git push origin master
    Counting objects: 9, done.
    Delta compression using up to 8 threads.
    Compressing objects: 100% (5/5), done.
    Writing objects: 100% (9/9), 705 bytes, done.
    Total 9 (delta 1), reused 0 (delta 0)
    To git@github.com:bramus/git-demo.git
     * [new branch]      master -> master
    
    bramus in ~/ikdoeict/git-demo on master
    $ 
    • If the remote repository is not empty … (see further)

Push & Pull

  • Publish locally committed changes
    $ git push origin master
    • Use git push and it'll default to origin and master
  • Pull changes from the server
    $ git pull
    • Will fetch the changes of the tracked branch and merge them into the locally active branch
      • In this example: origin/mastermaster

Inspecting remotes

  • List all remotes
    bramus in ~/ikdoeict/git-demo on master
    $ git remote show
    origin
  • Inspect one remote
    bramus in ~/ikdoeict/git-demo on master
    $ git remote show origin
    * remote origin
      Fetch URL: git@github.com:bramus/git-demo.git
      Push  URL: git@github.com:bramus/git-demo.git
      HEAD branch: master
      Remote branch:
        master tracked
      Local ref configured for 'git push':
        master pushes to master (up to date)

Branching

Imagine that this line represents time. At some point in the past, the timeline skewed into this tangent creating an alternate 1985.

Branches

  • The default branch is the master
  • List all branches
    $ git branch
  • Create other branches to develop experimental features
    $ git branch experimental
    • Branches are created locally
  • Activate (checkout) a branch
    $ git checkout experimental
    • The head will be moved to the new branch

Branching off

  • Creating an experiment branch based on the master
    bramus in ~/ikdoeict/git-demo on master
    $ git branch
    * master
    
    bramus in ~/ikdoeict/git-demo on master
    $ git branch experiment
    
    bramus in ~/ikdoeict/git-demo on master
    $ git branch
      experiment
    * master
    
    bramus in ~/ikdoeict/git-demo on master
    $ git checkout experiment
    Switched to branch 'experiment'
    
    bramus in ~/ikdoeict/git-demo on experiment
    $ git branch
    * experiment
      master
    
    bramus in ~/ikdoeict/git-demo on master
    $ 

Visualization



Visual representation of creating and switching to a branch

Committing changes

  • Changes are committed on the active branch
    bramus in ~/ikdoeict/git-demo on experiment
    $ touch exp.txt
    
    bramus in ~/ikdoeict/git-demo on experiment*
    $ git add .
    
    bramus in ~/ikdoeict/git-demo on experiment*
    $ git commit -m 'Start tracking exp.txt'
    [experiment a65b9d7] Start tracking exp.txt
     0 files changed
     create mode 100644 exp.txt
    
    bramus in ~/ikdoeict/git-demo on experiment
    $ git lg
    * a65b9d7 - (HEAD, experiment) Start tracking exp.txt (7 seconds ago) <Bramus>
    * c53f9b6 - (origin/master, master) Hello (15 hours ago) <Bramus>
    * 1d7a184 - Deleted test2.txt (16 hours ago) <Bramus>
    * f1c6883 - Start tracking test2 (17 hours ago) <Bramus>
    * 9c43f96 - Start tracking test.txt (22 hours ago) <Bramus>
    
    bramus in ~/ikdoeict/git-demo on experiment
    $ git checkout master
    Switched to branch 'master'
    
    bramus in ~/ikdoeict/git-demo on master
    $ ls
    drwxr-xr-x   4 bramus  staff  136 Mar 20 20:19 .
    drwxr-xr-x  11 bramus  staff  374 Mar 20 15:53 ..
    drwxr-xr-x  14 bramus  staff  476 Mar 20 20:19 .git
    -rw-r--r--   1 bramus  staff    6 Mar 20 14:38 test.txt
    
    bramus in ~/ikdoeict/git-demo on master
    $ echo 'on the master right now' >> test.txt
    
    bramus in ~/ikdoeict/git-demo on master*
    $ git add .
    
    bramus in ~/ikdoeict/git-demo on master*
    $ git commit -m 'on the master'
    [master 0ea8dd4] on the master
     1 file changed, 1 insertion(+)
    
    bramus in ~/ikdoeict/git-demo on master
    $ git lg
    * 0ea8dd4 - (HEAD, master) on the master (2 seconds ago) <Bramus>
    * c53f9b6 - (origin/master) Hello (15 hours ago) <Bramus>
    * 1d7a184 - Deleted test2.txt (16 hours ago) <Bramus>
    * f1c6883 - Start tracking test2 (17 hours ago) <Bramus>
    * 9c43f96 - Start tracking test.txt (22 hours ago) <Bramus>
    
    bramus in ~/ikdoeict/git-demo on master
    $ 

Visualization



Visual representation of committing on different branches

Merging changes

  • Include changes from an other branch with git merge
    • Changes made otherbranch are merged into the HEAD
      • Three way merge between common ancestor and two last branch snapshots
    • A merge commit is created
    bramus in ~/ikdoeict/git-demo on master
    $ git merge experiment
    Merge made by the 'recursive' strategy.
     0 files changed
     create mode 100644 exp.txt
    
    bramus in ~/ikdoeict/git-demo on master
    $ git lg
    *   965d016 - (HEAD, master) Merge branch 'experiment' (5 seconds ago) <Bramus>
    |\
    | * a65b9d7 - (experiment) Start tracking exp.txt (6 minutes ago) <Bramus>
    * | 0ea8dd4 - on the master (2 minutes ago) <Bramus>
    |/
    * c53f9b6 - (origin/master) Hello (22 hours ago) <Bramus>
    * 1d7a184 - Deleted test2.txt (23 hours ago) <Bramus>
    * f1c6883 - Start tracking test2 (24 hours ago) <Bramus>
    * 9c43f96 - Start tracking test.txt (28 hours ago) <Bramus>
    
    bramus in ~/ikdoeict/git-demo on master
    $ 

Visualization


Visual representation of merging changes

Cleaning up

  • Delete branches you don't need anymore
    $ git branch -d branchname
    • If a branch hasn't been merged yet, Git will warn you
    • Override warning using -D instead of -d
    bramus in ~/ikdoeict/git-demo on master
    $ git branch -d otherbranch
    error: The branch 'otherbranch' is not fully merged.
    If you are sure you want to delete it, run 'git branch -D otherbranch'.
    
    bramus in ~/ikdoeict/git-demo on master
    $ git branch -D otherbranch
    Deleted branch otherbranch (was e079840).
    
    bramus in ~/ikdoeict/git-demo on master
    $ 

Handling Conflicts

Hold tight!

Handling conflicts (1)

  • When merging, things can go wrong
    • e.g. the same line of code has been edited
    • When a merge conflict occurs, the merge will pause
    • Manual intervention (choosing which version to keep) is needed
    bramus in ~/ikdoeict/git-demo on master
    $ echo 'something for exp' >> exp.txt
    
    bramus in ~/ikdoeict/git-demo on master*
    $ git add .
    
    bramus in ~/ikdoeict/git-demo on master*
    $ git commit -m 'change exp.txt'
    [master babbcd3] change exp.txt
     1 file changed, 1 insertion(+)
    
    bramus in ~/ikdoeict/git-demo on master
    $ git checkout experiment 
    Switched to branch 'experiment'
    
    bramus in ~/ikdoeict/git-demo on experiment
    $ echo 'a different line for exp.txt' >> exp.txt
    
    bramus in ~/ikdoeict/git-demo on experiment*
    $ git add .
    
    bramus in ~/ikdoeict/git-demo on experiment*
    $ git commit -m 'change exp.txt (from experiment)'
    [experiment 2925064] change exp.txt (from experiment)
     1 file changed, 1 insertion(+)
    
    bramus in ~/ikdoeict/git-demo on experiment
    $ git checkout master
    Switched to branch 'master'
    
    bramus in ~/ikdoeict/git-demo on master
    $ git merge experiment
    Auto-merging exp.txt
    CONFLICT (content): Merge conflict in exp.txt
    Automatic merge failed; fix conflicts and then commit the result.
    
    bramus in ~/ikdoeict/git-demo on master*
    $ git status
    # On branch master
    # Unmerged paths:
    #   (use "git add/rm <file>..." as appropriate to mark resolution)
    #
    #	both modified:      exp.txt
    #
    
    bramus in ~/ikdoeict/git-demo on master*
    $ cat exp.txt 
    <<<<<<< HEAD
    something for exp
    =======
    a different line for exp.txt
    >>>>>>> experiment
    
    bramus in ~/ikdoeict/git-demo on master*
    $ subl exp.txt
    
    bramus in ~/ikdoeict/git-demo on master*
    $ git add exp.txt
    
    bramus in ~/ikdoeict/git-demo on master*
    $ git commit
    [master 80de07c] Merge branch 'experiment'
    
    bramus in ~/ikdoeict/git-demo on master
    $ 
    • → Fix the conflict, stage the file and commit

Handling conflicts (2)

  • Conflicted file contents
    <<<<<<< HEAD
    something for exp
    =======
    a different line for exp.txt
    >>>>>>> experiment
    • Resolve manually in a text editor
    • Choose version from HEAD
      $ git checkout --ours conflictedfile
    • Choose version from otherbranch
      $ git checkout --theirs conflictedfile

Rebasing (1)

  • Next to merging one can also rebase
  • No three way merge but
    1. Rewinds to the common ancestor
    2. Forwards to the last commit of the branch
    3. Applies the commits of the current branch on top of that state
    4. That final state is saved as the original branch
  • Roughly translated: inject the changes made on another branch into your branch to stay up-to-date.

Rebasing (3)

  • Rule #1 of rebasing
    • Don't rebase onto a branch that is shared with others
    • Put differently: only rebase on local featurebranches
    • Put differently, again: don't ever rebase onto your master
  • Rebase often to prevent potential merge conflicts
  • If the featurebranch is completed, merge it into the master

Rebasing Example

bramus in ~/ikdoeict/git-demo on master
$ git lg
* 1e7f02e - (HEAD, master) A change comtd on master (12 seconds ago) <Bramus>
* 80de07c - First commit! (2 minutes ago) <Bramus>

bramus in ~/ikdoeict/git-demo on master
$ git checkout experiment
Switched to branch 'experiment'

bramus in ~/ikdoeict/git-demo on experiment
$ git lg
* 669ae62 - (HEAD, experiment) A 2nd change comtd on experiment (34 seconds ago) <Bramus>* a9bdacb - A change comtd on experiment(69 seconds ago) <Bramus>
* 80de07c - First commit! (2 minutes ago) <Bramus>

bramus in ~/ikdoeict/git-demo on experiment
$ git rebase master
First, rewinding head to replay your work on top of it...
Applying: A change comtd on experiment
Applying: A 2nd change comtd on experiment

bramus in ~/ikdoeict/git-demo on experiment
$ git lg
* dba0673 - (HEAD, experiment) A 2nd change comtd on experiment (2 seconds ago) <Bramus>* 84484e4 - A change comtd on experiment(2 seconds ago) <Bramus>
* 1e7f02e - (master) A change comtd on master (54 seconds ago) <Bramus>
* 80de07c - First commit! (3 minutes ago) <Bramus>

bramus in ~/ikdoeict/git-demo on experiment
$ 
New commit hashes are generated as the patches are applied on top of the rewind/ffwd!

Visualization


Visual representation of git rebase

Visualization bis

Alternate visual representation of git rebase

Rebase conflicts

  • About the same scenario as when a merge conflict happens
    • Fix the conflict manually
    • Add the fixed file
      $ git add conflictedfile
    • Continue the rebase
      $ git rebase --continue
      • Aborting the rebase is also possible
        $ git rebase --abort

Publishing/Pulling branches

  • Publish a branch
    $ git push origin localbranch:remotebranch
  • Delete a remote branch
    $ git push origin :remotebranch
  • Create local branch based on remote branch
    $ git checkout -b localbranch remote/remotebranch
  • Update remote branch list
    $ git remote update

Collaboration

Yes, we have to work together, and not
have this fight I was definitely winning.

Collaboration

Collaboration

  • Knowing how to branch != knowing how to collaborate
  • When collaborating, maintain this flow
    # 1. Make sure the master is up-to-date
         $ git checkout master
         $ git pull
    
    # 2. Create a featurebranch based on the master
         $ git checkout -b featurebranch
    
    # 3. Develop, stage, and commit your feature on the featurebranch.
         When finished continue to step 4
    
    # 4. Make sure the master is still up-to-date
         $ git checkout master
         $ git pull
    
    # 5. Rebase the master onto the featurebranch
         (skip this step if master remained unchanged since step 1)
         $ git checkout featurebranch
         $ git rebase master
    
    # 6. Merge the featurebranch onto the master
         $ git checkout master
         $ git merge featurebranch
    
    # 7. Push the master
         $ git push origin master
    
    # 8. Clean up
         $ git branch -d featurebranch
    
    # 9. Rinse. Repeat

Few pointers

  • Don't ever develop on the master, but on featurebranches
    • In case that happens use git pull --rebase to minimize the situation and keep the master clean (#). From then on create a featurebranch and continue
  • The master must at all times contain deployable code
  • Keep your featurebranches local

Undoing commits

  • Undo last commit
    $ git revert HEAD~1
    • Creates a new undo commit → the faulty commit will always be accessible by checking out that commithash!
  • Possible to undo a commit without keeping it in the history only if it hasn't been pushed yet (two methods)
    $ git rebase -i commithash
    $ git rebase -i HEAD~2
    • Alternatively checkout the commithash before the faulty one and branch off

Github

Github

Github is …

  1. A website to browse Git repos
    • Browse branches
    • Inspect commmits (example)
    • Issues
    • Pull Requests
  2. A graphical Git client
    • Both Mac & Windows
    • Personal opinion: not recommended

Github is …

  1. A remote to push your repositories to
    • Public / Private (paid account)
  2. Embraced by the open-source community

PLEASE NOTE: GITHUB IS NOT GIT!

AGAIN: GITHUB IS NOT GIT!

Forking

If you don't like my code, Fork off!
  • Clone a repo from one github account to an other one
  • Create forks to develop your own features/your own version of the project
    • Develop on a local featurebranch
    • Publish featurebranch when ready to your own github remote
    • Do a pull request to see your changes implemented in the original project repo

Forking Flow

# 1. Create a fork on GitHub
     e.g. clone fabpot/Silex to bramus/Silex

# 2. Clone your repo locally
     $ git clone git@github.com:bramus/Silex.git

# 3. Create a featurebranch based on the master
     $ git checkout -b featurebranch

# 4. Develop, stage, and commit your feature on the featurebranch.
     When finished continue to step 5

# 5. Publish your featurebranch on Github
     $ git push origin localbranch:remotebranch

# 6. Do a pull request via Github and await merging

# 7. Rinse. Repeat.
     Make sure your master is in sync with the original master one!
     (add the original repo as remote and `git fetch` and `git rebase original/master`)

Merging Pull Requests

# 1. Checkout your master branch
     $ git checkout master

# 2. Add a new remote named 'otherdude'
     $ git remote add otherdude git://github.com/otherdude/Project.git

# 3. Fetch information about all branches on the 'otherdude' remote
     $ git fetch otherdude

# 4. Merge 'otherdude/featurebranch' into your master
     $ git merge otherdude/featurebranch

# 5. Push your newly-merged branch back to GitHub
     $ git push origin master

git.ikdoeict.be

Screenshots of git.ikdoeict.be

A few more things

Let's go. If I say one more thing,
I might say it with my evening boot.

Git Ignore File

  • Git will track all files in the working directory for changes
  • Ignore certain files by placing their name in .gitignore
    Thumbs.db
    app.db
    *.log
    vendor/*
    node_modules/*
    config.php
  • .gitignore must be committed into the repository

Config files

  • Don't commit config files such as config.php
  • Add config.php to .gitignore and provide a config.sample.php instead

Partially staging files

  • Commits must contain only one set of changes
  • In case of several changes, choose which changes may be staged in Patch Mode using git add -p file
bramus in ~/ikdoeict/ikdoeict-website on master*
$ git add -p index.html
diff --git a/index.html b/index.html
index 3fc8413..d7af84e 100644
--- a/index.html
+++ b/index.html
@@ -1,6 +1,6 @@
 <!DOCTYPE html>
 <head>
-	<title>Home | Ikdoeict.BE</title>
+	<title>Home | IkdoeICT.BE</title>
 	<meta charset="utf-8" />
 	<link rel="stylesheet" href="css/normalize.css" />
Stage this hunk [y,n,q,a,d,/,j,J,g,e,?]? y

@@ -176,7 +176,7 @@
     </section>
     <footer>
-	<p>Copyright (c) 2012 IkdoeICT.be</p>
+	<p>Copyright (c) 2013 IkdoeICT.be</p>
     </footer>
 </div>
 Stage this hunk [y,n,q,a,d,/,j,J,g,e,?]? n

bramus in ~/ikdoeict/ikdoeict-website on master*
$ git status
# On branch master
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#	modified:   index.html
#
# 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:   index.html
#

bramus in ~/ikdoeict/ikdoeict-website on master*
$ git commit -m 'title casing'
[master fc91e11] title casing
 1 file changed, 1 insertion(+), 1 deletion(-)

bramus in ~/ikdoeict/ikdoeict-website on master*
$ git diff index.html
diff --git a/index.html b/index.html
index 7602651..d7af84e 100644
--- a/index.html
+++ b/index.html
@@ -176,7 +176,7 @@
     </section>
     <footer>
-	<p>Copyright (c) 2012 IkdoeICT.be</p>
+	<p>Copyright (c) 2013 IkdoeICT.be</p>
     </footer>
 </div>

bramus in ~/ikdoeict/ikdoeict-website on master*
$ git add .

bramus in ~/ikdoeict/ikdoeict-website on master*
$ git commit -m 'copyright 2013 instead of 2012'
[master c36c7be] copyright 2013 instead of 2012
 1 file changed, 1 insertion(+), 1 deletion(-)

bramus in ~/ikdoeict/ikdoeict-website on master
$ 

Automatic publishing

  • Oldskool flow: uploaded changed files via FTP and run SQL updates through PHPMyAdmin
  • Thanks to Git some things can be automated

Automatic publishing

Practice!

  • I learned Git by just going for it. You should too.
  • I stil have much to learn about Git
    • … but I know how to Google when in need
    • … but I know how to read (a free book on Git)

Want more?!

  • Stashing
  • Tagging
  • Cherry Picking
  • Continuous Integration
  • Commit hooks

Questions?

(Press ↓ to see some frequently asked ones)

Why not just use Dropbox?

  • Yes, your files will be synced
  • But …
    • No proper collaboration (changes can be overwritten by others)
    • No all-of-the-time deployable code (mid development you cannot deploy your code)
    • No experimental features (you cannot start an experiment on a separate branch)
    • No author information (who broke what?)
    • No going back in time (limited to a few days in Dropbox)
    • No proper timeline (what, you're gonna zip up your files per feature developed? → That's versioning!)
  • And oh: don't ever share a folder that is a git repo

Do I have to remember all those commands?

  • No, sometimes I have to lookup one too.
    That's perfectly fine.
  • It's allowed to use a GUI but you should have a (vague) idea of what is happening in the background
  • Know the basic concepts (stage, commit, push, pull, merge, rebase)

I'll be fine without Git, right?

  • Alas, no dice. Whether you like it or not you'll have to use Git if you're ever going to do something in software/web
    • Above that it's a requirement for some of our courses
  • We know it's tough, but hang on until you get the gist of it
    • There's memory in repetition. There's memory in repetition
    • Truth be told, it took me over a year to get to know the commands I know right now, but I persevered.

Sources

ikdoeict.be