A couple of months ago, the local Ruby meetup group, BrisRuby, put out a call to see if anyone could do an introductory git talk. It ended up turning into two talks over two months. "Gitting Into Version Control: an introduction to git" and "Gitting Out Of Trouble: what to do when things go wrong".

I've written up the content in this blog post, and the slides are linked below.

Gitting Into Version Control

Why use version control?

  • It keeps a change history of every file
  • Branches let you, or several people, work on things concurrently
  • Auditing - where features were introduced, who worked on what

Why git?

  • Used by popular code hosting services like Gitlab, Github and Bitbucket
  • Creates a full copy of the whole repository (unlike SVN)
  • Open source
  • Powerful features

Initialise a repository:

$ git init --bare <directory>

Initialise a shared repository with --bare so that it doesn't create a working tree.

Clone an existing repository:

$ git clone <URL>

Edit the config:

$ git config --global user.name "Charelle Collett"
$ git config --global user.email "charcol@example.com"
$ git config --global --edit

Remove --global to change settings for a single project.

See what changes will be applied:

$ git status

Add files to commit:

$ git add <filename>

Or you can use -a while committing

Commit your changes:

$ git commit -m "message"

See the history:

$ git log

Move to a different branch:

$ git checkout <name-of-branch>

Create a new branch and move to it:

$ git checkout -b <name-of-branch>

Which is the same as:

$ git branch <name-of-branch>
$ git checkout <name-of-branch>

Show connections to other repositories:

$ git remote -v

Pull from a certain remote:

$ git pull <remote>

Push to a specific branch:

$ git push <remote> <branch>

Add a remote:

$ git remote add <name> <url>

Only push to a bare repository!

Remove a remote:

$ git remote rm <name>

Add branch config to .git/config:

$ git config --edit
[branch "new-feature"]
    remote = origin
    merge = refs/heads/new-feature

More info:

Git documentation:

https://git-scm.com/book/en/v1/Getting-Started

Atlassian's git tutorial:

https://www.atlassian.com/git/tutorials

Github / Code school interactive tutorial:

https://try.github.io/levels/1/challenges/1

Codecademy interactive tutorial:

https://www.codecademy.com/learn/learn-git

Gitting Out Of Trouble

There are many different ways to do the things mentioned here.

Rename a branch:

$ git branch -m <oldname> <newname>

Reverting uncommitted changes:

$ git checkout <file>
$ git reset --hard

Delete a branch:

$ git checkout master
$ git branch -D <branch>

If you have pushed:

$ git push --delete <branch>
$ git fetch --prune
$ git branch -D <branch>

Changing a commit message for the most recent commit:

$ git commit --amend

If you have pushed:

git push --force-with-lease

CAUTION: --force rewrites history

To change an older commit, you must rebase.

To delete a commit:

$ git rebase -i <previous-commit>

Then delete the line you want to remove.

If you have pushed:

$ git revert <commit>
$ git push

revert creates a new commit that undoes the changes

If you have committed to the wrong branch:

$ git branch <new-branch>
$ git reset --hard <commit>

If you have pushed:

$ git revert <commit>
$ git push
$ git checkout <correct-branch>
$ git cherry-pick <commit>

To squash commits / rewrite history / edit old commits / reword messages:

$ git rebase -i <commit>

or for the four most recent commits:

$ git rebase -i HEAD~4

Commits are shown oldest to newest. pick the oldest, and squash the newer commits. You can also reorder commits.

If you have pushed:

$ git push --force-with-lease

To get the latest changes and rebase onto those changes:

$ git checkout master
$ git pull
$ git checkout <branch>
$ git rebase master

If you have issues, you may want to rebase -i (interactive)

If there are conflicts and you need to manually merge, search for >>>> to find the conflicts.

Add the fixed files (git add <file>) then git rebase --continue. It's also possible to git rebase --abort

Reference log shows when the HEAD has been updated in the local repository:

$ git reflog [--all]

Stash changes:

$ git stash

Files need to be tracked before stashing. (git add . ) Or you can --include-untracked

Retrieve changes and remove them from the stash:

$ git stash pop

Remove from the stash:

$ git stash drop

Retrieve changes but keep them in the stash:

$ git stash apply

Small glossary

origin: default name for the repository you cloned from

working tree: where you edit the checked out branch (can have multiple)

clean working tree: current files you are editing match HEAD

bare repository: repository without a working tree. Pushing to a non bare repo can cause conflicts

staging: changes to be committed

HEAD: is the commit at the tip of the current branch

revert: creates a new commit to undo changes

reset: changes which commit HEAD is pointing to

Other interesting things

patch: Export changes as a patch that can be applied later

.gitignore: List of files that git should ignore

diff: See differences between commits

blame: See who was responsible for changes

More lessons on presenting

  • Even if you've increased the text size, someone will want it larger.
  • Even if HDMI works with your laptop on several different projectors, it won't always work on the one you're using ><
  • Even if a mini-DP adapter doesn't work on other projectors, it may work on the one you're using

The discussion afterwards is always my favourite part, because it's a chance to learn from other people. From this I found out that a colleague never uses git pull but instead fetch then rebase (since pull is a fetch then merge, this avoids the merge). You can find more detail in this excellent blog post: git: fetch and merge, don’t pull | Mark's Blog

Hopefully this is useful! Someone at the Ruby meetup suggested a potential future talk about different git workflows and branching models, but I don't think I have enough experience in different teams. Perhaps someone else would like to research and give this talk?