Git

Quick overview

Git is a distributed source control management tool. You can use it to track, review, revert changes (and much more) inside a directory.

how to sue git

Cloning

With Git, repositories are distributed. You can have a complete copy on your computer. There can be another copy in GitHub under the mnubo organization, there can also be another copy inside of GitLab under smartobjects if you want. None of them is truly the offcial repository. It’s up to you & your team to make a repository official.

For example, let’s say this repository is the official source code of the presentation: http://git-lab1.mtl.mnubo.com/dataviz/git-repo.

If you want to work on this project, you must clone it:

git clone gitlab@git-lab1.mtl.mnubo.com:dataviz/git-repo.git
cd git-repo
git status

Configuration

Git is configurable in a lot of ways. You will almost never need to configure it but there are some very useful things in there. As soon as you start to use it extensively, you’ll want to configure it so that it follows your workflow.

If you just installed git and you want to commit, you might get this error:

touch my-first-changes
git add my-first-changes
git commit

*** Please tell me who you are.

Run

  git config --global user.email "you@example.com"
  git config --global user.name "Your Name"

to set your account's default identity.
Omit --global to set the identity only in this repository.

This is your first encounter with the configuration. When you commit, you need to give your name and an email address because every commit will contain that information. Git has both a global configuration and a local configuration. This means you can set defaults in your global configuration but you can have specific configuration on a per-repo basis. For example, my global configuration states that my name is: David Francoeur and that my email is dfrancoeur04@gmail.com but when I work on mnubo’s project, I use my mnubo email address. Here’s how:

git config --global user.email "dfrancoeur04@gmail.com"
git config --global user.name "David Francoeur"
git commit -m "example of global configuration"
git show HEAD # you can see the values of the config in the commit itself

To set a local configuration value, remove the --global from the command line:

git reset HEAD^ # remove the last commit
git config user.email "dfrancoeur@mnubo.com"
git add test
git commit -m "example of local configuration"
git show HEAD # you can see the values of global config being overwritten

There is so much more to the configuration, you probably want to look into it. Here’s my global configuration:

cat ~/.gitconfig
[user]
    name = David Francoeur
    email = dfrancoeur04@gmail.com
[core]
    email = vim
    whitespace = fix,-indent-with-non-tab,trailing-space,cr-at-eol
    editor = vim
    autocrlf = input
[web]
    browser = firefox
[alias]
    rc = rebase --continue
    ra = rebase --abort
    ri = rebase -i
    cf = commit --fixup
    co = checkout
    cb = checkout -b
    ria = rebase --autosquash -i
    cob = checkout -b
    com = checkout master
    can = commit --amend --no-edit
    rsh = reset --hard
    ca = commit --amend
[color "diff"]
    whitespace = red reverse
[gitrepo "mnubo"]
    token = *******
    type = gitlab
    fqdn = git-lab1.mtl.mnubo.com
[pull]
    ff = only

Making and sharing changes

Git uses a two phases commit system. You use git add to put changes on the stage and you use git commit to actually save your file in the repo. This allows for plenty of things and I will explain it further in the rest of the post.

git files lifecycle

Remotes

In the configuration section, we’ve introduced a commit. This commit exists in out local copy of the code, but nobody else can see it. How do we share it with the rest of the world. You can push it directly to the repository we cloned earlier, but it’s not recommended because you would not allow your peers to review your work (in theory, you should not be able to push directly into the official repository). Here’s how:

git status
git push origin master

What’s in the command above? We tell git to push our changes to origin on a branch master. What’s origin and what’s that branch master?

By default, when we cloned the repository initally, git added a remote called origin, this remote point to the repository we cloned. Remember when I said that git was distributed? Well, git deals with that with remote. Remotes are different places where the code base you are working with is located. You can fetch and push changes to these remotes. You can see the remotes with this command:

git remote -vvv

Branches

The branch master is automatically checkout out when we clone because the remote is configured to use this branch as the default. It is configurable: http://git-lab1.mtl.mnubo.com/dataviz/git-repo/edit.

You can create your own branches with git branch. You can also move from one branch to another with git checkout. A branch is simply a pointer to a commit series of commit.

git branch new-branch
git checkout new-branch
git checkout -b new-branch # a shortcut for the two above

Merge Requests

So we know how to push to the repository we cloned. But if we do so, we do not allow out colleagues to review our changes. How do we that? There are different ways to do code review, but at mnubo, we use the GitLab interface to do our reviews. Usually, the whole process is called a Merge Request (MR, it can also be called a Pull Request, PR, in other systems). To do a merge request with GitLab, you fork the official repository and make changes to this copy. Afterward, you open a merge request on GitLab.

When you have forked the repository, you get a clone of it. The url is slightly different the official repository: gitlab@git-lab1.mtl.mnubo.com:dataviz/git-repo.git vs gitlab@git-lab1.mtl.mnubo.com:dfrancoeur/git-repo.git

We can add this fork to our local repository with git remote but before we do that. Let’s give another name to our origin remote so we make it more official:

git remote rename origin upstream # I use upstream here, but you can use anything

Now let’s add a new remote to point to our fork and push the commit in our fork:

git remote add origin gitlab@git-lab1.mtl.mnubo.com:dfrancoeur/git-repo.git
git push origin master

When the changes are pushed, you can open Gitlab and make a pull request: http://git-lab1.mtl.mnubo.com/dfrancoeur/git-repo/merge_requests/new

Now your peers can review and merge your changes.

Scenarios

Now I’ll show some more complex things in the form of “scenarios”.

Scenario #1

You open your merge request, and after review, the only thing that stands out is a coworker that asks you to rebase your work. What does that mean?

This happens because as you were working with a copy of your local repository, the official repository was being updated by your peers. New commits were introduced and your version do not contain them. Gitlab will allow you to merge the changes if there are no conflicts but doing so will ruin the history.

You can rebase your changes on top of the changes that happenned in the official repository so you get to keep a clean history.

Show: git rebase upstream/master

Scenario #2

You are working on a feature and the amount of changes is getting quite big, it might be relevant to break the upcoming MR into pieces so your reviewers can understand it. For example, you decided to refactor some piece of code that is used throughout the project. You can open a MR with this small subset of changes, continue working.

Show: git add -p, git rebase -i

Scenario #3

You commit multiple times with different changes. After a while, you realize that you forgot to do something and that some new changes should go inside a commit you’ve already done. You can update the existing commit with a rebase.

Show git commit --fixup, git rebase --autosquash