This tutorial will be a loose guide to reduce the pain of using the git command line for the first time. This requires you to have at least another person to work with. The fictitious setup is to move an existing project into version control (git) and further develop it with your friends / colleagues.
We provide the following sample projects for you to work with Git:
- A Python application
sample_game.zip
- A LaTeX Document
sample_report.zip
Pick one based on your skills. And we can proceed.
Note
Only one person in the team must do this part. The others team members can read ahead and / or give instructions while enjoying their drink. Alternatively, all members can do this part, but then for the later parts, you will use only one person’s work to continue the tutorial.
-
Unzip your chosen project somewhere
-
Open a terminal in the root directory of the project. Windows:
Git Bash Here
, MacOS:Services > New Terminal at Folder
, Linux: you got this -
Initialize a Git repository
$ git init
You can see that git is not tracking anything yet by reading the output of
$ git status
This will initialise a git repository. If you enable hidden files in Explorer (View > Hidden Items
) or Finder (CMD + Shift + .
) you will see that it has created a .git
directory.
Next, we need to add the existing files to git. Before doing so it recommended to avoid adding useless files (e.g. temporary files generated by the OS), so we must tell git to ignore such files:
-
Create an empty text file in the project directory called
.gitignore
(yes, it must start with a dot) -
Go to gitignore.io and add relevant tags, for example
Windows, MacOS, Linux, Python
orLaTeX
and copy the string generate by the website into the.gitignore
file. On MacOS / Linux you can also do this directly from the terminal$ curl https://www.toptal.com/developers/gitignore/api/latex,linux,macos,python,windows > .gitignore
You can also do it by hand (without the website), the syntax is not difficult to learn.
-
Run in the terminal
$ git status
You should see under
Untracked files:
a list of files in red that git is detecting are not part of the repository. Check that there are no useless files such asThumbs.db
,.DS_Store
,Report.aux
. You can see git tells youuse "git add <file>..." to include in what will be committed
-
Add the existing files or directories to the staging area using
$ git add README.md src ... # add all files
Adding directories will recursively add all files within them. Or shorter if you want to add all files at once
$ git add --all
Warning
Do not abuse the --all
flag. In general you should carefully chose what files to add. By carelessly using --all
in large projects you might accidentally add cryptographic secrets, files that are gigabytes in size, etc..
-
Run again
$ git status
Now you will see the files have turned green, they are in the staging are and git says
Changes to be committed:
above them. -
If the list of file looks good you can create your first commit with
$ git commit
This will open your editor of choice (while the terminal is waiting). You will see a summary of the changes, these will not be part of the commit since if you read you will see the message
# Please enter the commit message for your changes. Lines starting # with '#' will be ignored, and an empty message aborts the commit.
Above these you can add your commit message. In this case there is not much to say except, for example write:
Move project into version control
.You can save the file and close the editor. In the terminal you should see a summary
STUB [master 5c40c24] Move project into version control 2 files changed, 36 insertions(+), 1 deletion(-)
You have successfully created your first commit in the master
branch (the default branch name used by Git).
All members go to GitHub and register an account if they don’t have one yet. After that each user must configure their account such that they can authenticate their computer with GitHub. You will only need to perform this task once.
Note
Git uses the SSH protocol which uses public-key cryptography to synchronise the repositories across computers. Git can also work with HTTPS authentication but then for security reasons GitHub requires you to use authentication tokens, which are annoying. We stick to SSH.
If you have never used SSH or don’t have an SSH key pair you need to generate it:
-
Run the following command replacing the email address with yours and follow the instructions on screen. You can press
ENTER
a few times to use the default settings.$ ssh-keygen -t ed25519 -C "[email protected]" # replace with your email
This will generate an SSH key pair using elliptic curve cryptography.
-
Copy your public key. If you read the output of the previous command you will see where it was saved
Your public key has been saved in ...
. By default it will be in your home directory. To read your public key you can open the file with your editor or in the terminal run$ cat ~/.ssh/id_ed25519.pub # or wherever it was saved
-
Copy your public key which should look something like this (note: this is not my public key, but one generated for this example)
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPLVAByZGT6xWM2kg7AeEkXbujOETnHdw2FOUx3/mpow [email protected]
-
On your GitHub profile in the browser go to
Settings > SSH and GPG Keys > New SSH Key
and paste your public key, leave the key type settings to anAuthentication Key
.
You will now be able to authenticate your computer with GitHub.
The person that has done all of the steps so far (in part 1) needs to create a remote repository on their GitHub profile.
-
Go to github.com/new and create a new repository. Do not pick a template, leave it to public, and hit
Create Repository
. If you don’t know what to call repository set the name togitws25
.After a while you will see the repository has been created on your profile. There will be instructions on the website on how to upload your code. We will follow
... or push an existing repository from the command line
. Before following the instructions make sure that in the blue shaded area you have selectedSSH
-
In your terminal you can add the remote with
$ git remote add origin [email protected]:YOUR_USERNAME/gitws25.git # replace with your remote URL
This will let Git know that there is a server named
origin
(name is local to your machine) at the GitHub URL. You can also call it something else, likegithub
instead oforigin
(note that for the rest of this tutorial we will useorigin
, you can use a different name but you will need to update the next command accordingly). -
Now we can push our first commit to
origin
with$ git push --set-upstream master origin
The
--set-upstream
flag will setorigin
to be the default remote to push to. After setting this once you will be able to write justgit push
, and it will push toorigin
. -
Now, if you refresh the browser you should see that your file have been uploaded to GitHub.
The other members can finally do something. Hopefully they are not drunk yet.
-
For the person that had been leading so far: Add your other team members as collaborators by going to
Settings > Collaborators > Add People
and adding their GitHub usernames. -
The other members can see on their email inbox or at github.com/notifications an invitation to join the project. Accept the invitation.
-
The other members can clone the project onto their machines. Open terminal where you want your project to go. In the browser from the green
Code
button under SSH you can get the URL to clone the repository with the command:$ git clone [email protected]:YOUR_TEAM_MEMBER/gitws25.git # replace with your remote URL
We will finally start to do something interesting with the Git commit graph. First we do a fast-forward merge, we need two people, which we will call Alice and Bob. To make it interesting for the group, we will work with remotes branches, even though the theory is the same for local branches.
-
Alice: In the project folder there is a file
TODO.txt
with a list of things to do, pick any task you like and perform the change in the project code. After saving the files you can see your changes underChanges not staged for commit: ...
in the output ofalice $ git status
You can quickly add the files you have changed with the staging area using the
--update
flag:alice $ git add --update --all # add all files that are tracked
Commit your changes with an appropriate commit message, and push your changes to the remote repository (GitHub). The
--verbose
will allow you to see the changes in the editor for the commit message:alice $ git commit --verbose alice $ git graph # see your new commit. or git log if you do not have the alias alice $ git push origin master
Tip
If you have used the --set-upstream
flag earlier, you can just write $ git push
instead of repeating always $ git push origin master
.
-
Bob: Fetch Alice’s changes and take a look at the commit graph before merging. You have no local changes, only the ones from remote. You only need to “catch up”:
bob $ git fetch origin # download new commits from remote bob $ git graph # take a look at the commit graph bob $ git merge origin/master # merge the changes into your local master branch
If you read the output of the last command, it will say that is it a fast-forward merge. Now the two computers are in sync. If you are team of 3, for this part there can be “two Bobs”, i.e. two people can play the role of Bob.
You should be starting to get how this work. We will give less detailed instruction from now on. We will now perform a true merge (aka 3-way-merge).
-
Alice and Bob: Pick any task from
TODO.txt
and do it. Pick different tasks. Add your changes to the staging area and commit$ git add ... # add the files you changes $ git commit # with a good commit message
-
Alice: Upload your changes to the remote repository
alice $ git push origin master
Tip
If you struggle visualising what is happening in your head. Take a piece of paper and draw the commit graphs on each machine, as was done in the presentation slides.
-
Bob: Download Alice’s changes and observe that your commit graph has a branching commit (histories diverge)
bob $ git fetch origin # get changes bob $ git graph # histories diverge bob $ git merge origin/master # get the new changes
After running the last command, the editor will pop up, because to perform this merge you need to create a new commit, with a commit message. You can leave the default
Merge branch origin/master into master
, save it and close. You should now have both your and Alice’s changes.
Caution
Bob: Make sure the are no uncommitted (therefore unsaved) changes, otherwise the merge will fail, telling you that it would overwrite your unsaved changes. If you have some changes by mistake, you can discard (delete) them using
$ git restore FILE # DELETES your changes in file!
-
Bob: Push the newly created merge commit to the remote
origin
bob $ git push origin master
-
Alice: Download Bob’s changes and do a fast-forward merge
alice $ git fetch origin alice $ git merge origin/master # will be a ff-merge
Or in one command:
alice $ git pull origin # fetch and merge
Now the two computers should be in sync. If there are other team members, they can also pull from origin to sync their repository.
Note
Now we will repeat the same process, but we will also intentionally cause a merge conflict, so that you can learn how to deal with them. You can switch roles if you want.
-
Alice and Bob: Pick the same task from
TODO.txt
and edit the same file at exactly same lines, but make sure they are different on each machine. Add your changes and commit them. Make sure you do not have uncommitted changes using$ git status
. -
Alice: Push your changes to the remote.
-
Bob: Fetch the changes and merge, or do both at once using pull. You will get an error message. Git will tell you that there was a merge conflict, it should also tell you in which file it happened. Now, if you open the editor and take a look at the file you edited in point 6 you will see something like this
<<<<<<< HEAD Your local changes (Bob's) ======= Remote changes (Alice's) >>>>>>> 75d041...
Git has added
=======
where the conflict happened, on one side you should have your changes, while on the other Alice’s. If you run in the terminalbob $ git status
You will see (read) that you are in the middle of a merge
You have unmerged paths.
, and Git will tell you which files caused the merge conflict underUnmerged paths:
. -
Bob: To manually resolve the conflict. You need to choose one of the changes (for this tutorial it does not matter which one), then delete the other changes you do not want, the line
=======
, as well as the other two lines with<<<<<<<
and>>>>>>>
, and save the file. Then you can continue the merge that had failed by completing the merge commit:bob $ git add ... # add files that caused conflict, and have been fixed bob $ git commit --verbose bob $ git graph # take a look at the commit graph
Tip
It is good to resolve a merge conflict by hand at leat once as learning experience. For actual work though, there are many graphical tools that show you the two options and do the deleting automatically for you (though usually not adding and committing in Git). See slide on Graphical User Interfaces.
-
Bob: Push your changes to remote
-
Alice: Fetch and merge (pull) Bob’s changes. The two machines should be in sync.
Note
This subsection is about software development and project management. You can move to the next part if you are not interested in the topic.