Create a gist now

Instantly share code, notes, and snippets.

@marchelbling / Secret
Last active Aug 29, 2015

git exercices

Hands on git!


  • install git (prefereably 2.0.0+)
  • define git user
    • git config --global "My Name"
    • git config --global ""
  • (optional) setup bash completion
  • (optional) setup custom prompt
  • (optional) signup on GitHub (see student pack)


  1. conflicts
  2. branches and remotes


Refer to the course material or Pro Git or StackOverflow when in doubt. And use git reflog when in panic!

Common git commands:

  • git init: initialize new local repository
  • git clone: initialize repository from remote
  • git status: show current state
  • git reflog: show history of commits (even no longer reachable)
  • git add: stage content
  • git rm: remove file from tracking
  • git commit: create new revision based on staging area
  • git branch: control branch lifecycle
  • git checkout: set local filetree to revision (also used to create new branch with -b)
  • git reset: set commit tree to revision (along with filetree when --hard)
  • git merge: join 2+ branches together
  • git rebase: rewrite branch history
  • git cherry-pick: apply changes from commit
  • git log: list commit tree
  • git show: show commit data
  • git diff: compare commits
  • git push: publish branch
  • git fetch: update remote namespace
  • git pull: update upstream remote and merge/rebase current branch
  1. Create a repository

  2. Clone the repository locally (use https protocol to avoid proxy issues or ssh configuration).

  3. The root commit of a repository is special as it does not have a parent commit. A good practice is to initialize the commit tree by committing a file describing the purpose of the repository.

  4. To make sure that every line of code is product driven, the team lead wants to make sure every commit is referenced to a story in the project management tool. To do so, the team will have

    • to use a task type as branch prefix (feature/bug/hotfix/chore) and
    • to reference a story id (a number composed of 8 digits exactly) as branch suffix

    A branch will then have to look like feature/add-functionality_12345678 or bug/wrong-stuff_87654321. To ensure this policy, the team will use hooks. git hooks offer the possibility to add custom behaviors on top of some git actions:

    Hooks have to be executable and should be placed in the .git/hooks folder. Hooks thus can not be enforced within a repository. Another team already uses a similar process:

    • create a new branch feature/pre-commit-hook
    • cherry-pick master’s HEAD from to get the pre-commit hook
    • fix any conflict in you editor and git cherry-pick --continue
    • make sure the code fulfills the team requirements:
      • install the hook in your repository
      • check what happens when creating a feature or a bug branch
    • merge feature/pre-commit-hook in master.
  5. For obscure reasons, the team lead would like to try a "rebase strategy" in a new repo. With such a workflow, branch names disappear when integrated in the trunk. The team lead thus wants each commit to refer to a story using "[#12345678]" as message prefix. It seems that the hook from could do the job:

    • checkout the prepare-commit-msg file from the repository master’s HEAD
    • install and test the hook
    • when everything is working fine, commit the hook on master.
  6. Hooks have been running fine for a while. However, we realize that in some occasion, code is pushed that does not belong to a story e.g. hotfixes need to go live quickly. Also it happens that we need to commit something directly on the develop branch. The team lead thus wants to change the rule and allow commiting on hotfix, develop and master without referring to a story.

    • create a branch feature/special-branch-no-hook
    • update hooks to satisfy the new specification and commit the result
    • merge into master using the --no-ff flag
  7. The team lead wants to make the updated team hooks available to the core team. Push the hooks:

    • to the master branch if you use a gist (note that you can push to any branch but it will just be lost)
    • to a branch feature/updated_hooks if you have a "full" repository

    You can then email the link of your gist/repository to the core team lead ( to let him know that you have a nice hooks update!

  8. The team lead has noticed that new members of the team often push code with lots of typos! We want to make sure that when a branch is pushed it will at least compile properly. You need to update the hooks to make sure of this. Making sure that everything compiles before pushing is probably enough.

    Note: as we will never want to version the compiled code, you could add the build folder in .gitignore to prevent anyone from inadvertently versioning those files and not clutter the git status command with untracked content.

  9. A new team lead has arrived. He does not like bash for string manipulation. You have been asked to rewrite the hooks in C/C++ while respecting the DRY principle (i.e. code should not be duplicated).

As mathematicians, we need a playground to manipulate new objects. Let’s therefore create a local repository:

$ git init $HOME/playground
$ cd $HOME/playground
$ echo "A mathematical playground" >
$ git add && git commit -m "Reinventing mathematics"

We have heard of new developments in the set theory and need some simple data to play with

$ echo "{}" > data && git add data && git commit -m "zero"
$ echo "{0}" >> data && git add data && git commit -m "one"
$ echo "{0,1}" >> data && git add data && git commit -m "two"
$ echo "{0,1,2}" >> data && git add data && git commit -m "three"

The fellow Bogdanov brothers have indeed proved that mathematics are wrong and three is actually two and two is three. We therefore need to rewrite history using

$ git rebase --interactive HEAD~3

and then need to swap the two commits lines. What happens? Why?

Bonus: as mathematicians, we should be careful and probably we should not accept so impacting claims easily. We would have probably be better exploring this new idea using a branch:

  1. let’s go back in time: use git reflog to find the commit before our rebase attempt (hint: it should be HEAD@{4})
  2. go back to this revision using git reset --hard <commit>
  3. create a dedicated branch git checkout -b bogdanov
  4. modify data with the Bogdanov hypothesis
  5. merge in the master branch: git checkout master && git merge --no-ff bogdanov

What is the difference with the previous approach? Why?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment