GitLabTM[1]#
Objectives📍
What is GitLab
local vs. remote repository
push
pull
clone
fetch
merge
Merge conflict between your local and remote repository
As mentioned in the introduction, GitLab is a platform for collaborative code development. Everything we did so far in this Git course we did on our local machine and nobody has access to our project. Because collaboration is a major part in science, we need to be able to have a centralized workflow without needing to send all of our files back and forth with emails. This is very cumbersome and also no one ever knows what is the current version because between sending an email and actually getting feedback some time will pass. By putting your project on a centralized repository and giving your collaborators access to this repository, they will:
always see the latest version of the project
see the development stream of the project (aka commit history)
they can retrieve the project and make changes and either commit them directly or ask you if you want to incorporate those changes (
merge request
)they can comment on it
they can open a discussion (
issue
)and much more…you can even do project management on gitlab if you want to
All we have to do is to set up a remote repository on gitlab and synchronize our local work with this remote repository. First we need some more vocabulary:
More Git vocabulary
git push
: synchronize your local repository with the remote repository by pushing changes in the local repository into the remote repositorygit pull
: synchronize your local repository with the remote repository by pulling changes from the remote repository into the local repositorygit clone
: this gives you an exact copy of a remote repository on your local computergit fetch
: fetching the latest version from the remote repository into your staging area
Task 9
go to gitlab.com and log in
click on “new project” –> “create a blank project”
give the project the name
choice_rtt
under “Project URL” select your name
select “public” as visibility level
uncheck the box “Initialize with a README”
We are now presented with this page:
This page basically presents you with different options on how to fill your gitlab repository. Because we already have a git repository, namely our choice_rtt
project on our local machine, we need the last option “Push an existing git repo”.
Task 10
Follow the instructions given by gitlab for “Push an existing git repo”. After you did all of this, refresh the page.
I get an error when I push via ssh
First, please check that you followed the GitLab ssh instructions on the setup page. If you did and it doesn’t work, it’s likely that the ssh connection to gitlab wasn’t properly stored in your .ssh config
. Here’s how you can solve this:
navigate in the terminal to your
.ssh
folder. It’s in your root directory, socd ~/.ssh
should work for everyoneinside this folder, check if you have
config
file by typingls
if you see a file named
config
in the list open it. If not, create this file. Both can be done by typingnano config
(if you have nano as a text editor). Other ways can betouch config
orvi config
, whichever works for youinside this file you have to write the following (watch the indentation!):
Host gitlab.com HostName gitlab.com IdentityFile ~/.ssh/id_ed25519 # replace id_ed25519 with the name of your own ssh key
save and close the file and try
git push --set-upstream origin --all
again
If that still doesn’t work, you can also chose HTTPS
instead of ssh. For this I recommend using a Personal Access Token
. Because if you use https for push/pull/clone etc., you will always be asked for your username
and password
. However, if you use a personal access token, you only have to use it once and git will remember it. For creating a personal access token, follow these steps:
click on your profile on the upper left and select
Preferences
go to
Access Tokens
on the left sidebarclick
add new token
give it a name (e.g., the name of the machine you’re currently using, like “julia’s macbook”), delete the
expiration date
, and clickapi
underselect scopes
click
create personal access token
copy your token (THIS IS SUPER IMPORTANT! This is the only time you can actually see your token on gitlab, after that it will never be shown to you again, so please make sure to copy and save it somewhere you can find it again!)
go to your terminal and type the following one after another:
git remote rename origin old-origin
git remote add origin https-link-of-your-repo
–> you can find the https link by going to your gitlab repo and clicking on the bluecode
button on the upper right and switch tohttps
git push --set-upstream origin --all
now it will ask username and password. Give your
username
but instead of the password, put your access token!
I hope it worked!
Through the command git push --set-upstream origin --all
we set up remote branches to track our local branches. The remote branches have the same names as our local branches but have a origin/...
added. That’s how git can distinguish local and remote work.
Local vs. Remote Repository
The local and the remote repository are two different things. You need to actively initiate the synchronization between the two (push-pull).
One important thing to remember for understanding how the synchronization between git and GitLab works is:git makes you think you work on the same branches locally and remotely: they follow the same working stream and share the same version history, you don’t need to switch between branches. But technically it’s handled as if it’s different branches: main
vs. origin/main
. This is necessary for the communication between local and remote repository to enable functions like git merge
and git diff
.
Let’s take a look at how the main page of a gitlab repository looks like:
at the top left we can see which branch of the project is currently displayed in the remote repository. When you click on it, you can change the branch and the files shown will automatically update according to the state of the files on this other branch
on the top right you’ll find the code for the repository which you (and others) will need to connect to the gitlab repo, for example for cloning the repository
the marked part in the middle shows a commit message. Here it becomes evident why you should not just blindly add and commit everything at once. Because here you can see that your commits are bound to your files. If you always do
git add .
and commit, all your files will have the same commit message so the benefit of seeing at first sight what was last changed in this file is lostLastly, you can see that README files in your repository will always be automatically rendered on the main page of the repo. This is another reason why you should have a nice and informative README file for your project
gitlab in VSCode#
Now that we have our project on gitlab, VSCode automatically noticed that we have a remote repository involved. When you click on the git graph on the left bar you can see the remote repository under SOURCE CONTROL REPOSITORIES
and when you click on the arrow next to commit
you can see that now you also have the option to commit & push
with one click.
gitlab as an Add-on on OSF#
On Monday we created a project on OSF for our choice_rtt
project. Of course, we want to share our code and data there. Because we do have everything in a public gitlab repository we can simply create an Add-on for gitlab on our OSF project and all the files will be added to the OSF repo. The advantage in having both, gitlab and OSF (or another data repository) is that OSF can give you a DOI, gitlab cannot. Also, in our case we can put the data on gitlab, because we have very little data and small files. However, gitlab is NOT a data repository but a code development platform. So, if you have lots of data you will need to have it separately. E.g., have the data on OSF and code on gitlab and combining it via the gitlab Add-on on OSF with just a simple click.
Task 11
Go to the OSF project you created on Monday and add the GitLab repository.
Working collaboratively#
Because gitlab is the best to learn via working collaboratively, this is what we will do!
Task 12
Find a partner. Choose one of your gitlab repos to be the one you will both work on during the rest of this session
Add the person who is not the owner of the repository as a project member with the role “Developer”
From now on the owner of the repository is called owner
and the collaborator is called developer
.
developer
clones the repository:navigate with the terminal to your desktop
got to the
owners
gitlab repo by searching for their name. Click on the respective repo.click on the
code
button on the upper rightcopy the “clone via ssh”
type in your terminal
git clone repo-link-you-just-copied
developer
opens a file, makes a change, adds and commits itdeveloper
pushes the change to the repo by doinggit push repo-link-you-just-copied
owner
refreshes gitlab repo to see if the change was updatedowner
needs to incorporate the changes from the remote repo into the local repo:git pull repo-ssh-link
owner
opens a file, makes a change, adds and commits itowner
pushes the change to the repo by doinggit push
Instructions for doing this exercise alone
create a new folder on your desktop called
developer
andcd
in itclone your own repository into the
developer
folder:click on the
code
button on the upper rightcopy the “clone via ssh”
type in your terminal
git clone repo-link-you-just-copied
follow the instructions above by switching between the original folder and the cloned repo in the
developer
folder (best is to open to separate VSCode windows to not get too confused)
For the following tasks, owner
refers to your “original” folder, and developer
refers to the new folder that has the clone in it.
Project Member Roles and Permissions
The list is sorted from all to nothing, meaning the next lower level inherits the restrictions from the higher level.
Owner: can do anything that is possible on the repository
Maintainer: can’t delete anything; can’t assign, archive, transfer project or change visibility level
Developer: + can’t manage gitlab pages; can’t change container registry and application security
Reporter: + can’t manage incidents
Guest (This role applies to private and internal projects only.): + can’t manage issues, merge requests; has almost no project management permissions
git clone
if you clone a repository it will only clone main
to get the other branches of the remote repo:
git branch –a
shows you all available branches (e.g., origin/eyetrack)git checkout eyetrack
: creating a local Branch and git automatically detects that there is a remote sibling branchgit output: branch ‘Party2’ set up to track ‘origin/eyetrack’
repeat for every branch you want to have locally available
git pull
git pull
means you are pulling the version from the remote origin branch directly into your working directory which also means an automatic merge of remote and local branch. It therefore updates your git repo AND your working directory in one command.
git fetch
git fetch
means that git is updating the remote branch in your local git repo calledorigin/main
where it contains the latest remote version of the project. It is not updating your local branchmain
.that’s why you have to (or can) merge: your corresponding local branch
main
in your working directory contains a different version of the project than the remote branchorigin/main
that’s also the reason why you can do git diff: it compares our
main
branch in the working directory with theorigin/main
branch in the git repogit fetch
is helpful if you want to inspect the changes from the remote repository first before incorporating them locally. Because maybe a merge conflict is hiding in the remote version
Summary gitlab workflow#
Merge conflict between local and remote repository#
Like mentioned previously, merge conflicts are not unusual and happen more often when you work collaboratively. It is very likely that your collaborator works on the project at the same time as you and sometimes those changes overlap. This is why we want to practice how to solve a merge conflict with the remote repository.
Task 13
work with your partner from the previous task again
developer
does agit pull
developer
andowner
both make a change to the project at the same spot, e.g., modify the same line in the instructionsdeveloper
does agit push
firstthen
owner
does agit push
owner
should get a message saying:
rejected! error: failed to push some refs to ‘repo url’
hint: Updates were rejected because the remote contains work that you do not have locally. This is usually caused by another repository pushing to the same ref. You may want to first integrate the remote changes (e.g., ‘git pull …’) before pushing again.
This error message is not due to the merge conflict but due to the fact that owner
made one more commit to the commit history and therefore expanded the commit history. As you both work on the same branch and git works in a linear way, git cannot put two commits at the same place but only one after another. So git expects you to have the latest version with all commits before you make another one. So, you will also receive this message when you don’t have a merge conflict but simply didn’t pull the latest version first.
Task 14
work with your partner from the previous task again
owner
does agit pull
owner
should get a merge conflict message like the one we saw beforeowner
needs to resolve merge conflict (we learned how to do that already, yeah!)owner
can now do agit push
Tips for working collaboratively with git
make use of
branches
. Sometimes weird things happen when everyone is committing to the main branch all the time. Just create a branch for your own work andmerge
the updates frommain
into your branch regularlymake use of
merge requests
(we will learn this in the next section). This way you can incorporate a second communication channel with your collaborators and give them a chance to not only inspect but also discuss the changes before merging them into themain
branchbefore you start your work at the beginning of your day, do a
git fetch
, inspect the changes, andmerge
them