Git is a distributed source control management tool. You can use it to track, review, revert changes (and much more) inside a directory.
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 firstname.lastname@example.org:dataviz/git-repo.git cd git-repo git status
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 "email@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 firstname.lastname@example.org but when I work on mnubo’s project, I use my mnubo email address. Here’s how:
git config --global user.email "email@example.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 "firstname.lastname@example.org" 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 = email@example.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.
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
origin and what’s that branch
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
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
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: firstname.lastname@example.org:dataviz/git-repo.git vs email@example.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 firstname.lastname@example.org: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.
Now I’ll show some more complex things in the form of “scenarios”.
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.
git rebase upstream/master
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.
git add -p, git rebase -i
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.
git commit --fixup, git rebase --autosquash