Skip to content

Latest commit

 

History

History
456 lines (297 loc) · 20.8 KB

Tutorial.md

File metadata and controls

456 lines (297 loc) · 20.8 KB

Hands-on Phase Tutorial

This tutorial will be a 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 and further develop it with your friends / colleagues.

This tutorial was written by me without use of ChatGPT. I do not have a Nobel in literature, but please read every sentences, I promise they are necessary and concise.

Configure Git on your Machine

After having installed Git we first configure git. Open a terminal: Windows Git Bash, MacOS Terminal.app, Linux: use your favourite. The first thing you have to do is tell git your information

$ git config --global user.name "Your Name"            # Name shown in commits
$ git config --global user.email your_email@domain.ch  # E-Mail shown in commits

Next define a new command git graph to visualise the commit graph in the command line. We will use this command throughout the tutorial:

$ git config --global alias.graph "log --all --decorate --graph --oneline"

We set that we want that pull is an alias for fetch + merge (it can also be configured to be fetch + rebase, more on this later):

$ git config --global pull.rebase false

Then the following commands to set some sane defaults, mostly taken from this article if you are interested in the details:

$ git config --global init.defaultBranch master # default branch is called master
$ git config --global diff.algorithm histogram  # improves output of git diff
$ git config --global fetch.prune true          # delete remote branches is they no longer exist
$ git config --global fetch.pruneTags true      # same for tags
$ git config --global fetch.all true            # always get all remote branches

Finally we set up a simple text editor to write the commit messages. Unless you have customised it differently during the installation the default editor is VIM, which is very powerful but not user friendly at all.

Windows

For Windows we can use Notepad.

$ git config --global core.editor notepad

MacOS

On MacOS this will set the editor to Text Edit

$ git config --global core.editor "open -e -W -n"

Pick a Project

We provide the following sample projects for you to work with Git:

  • A Python application (Game) sample_game.zip
  • A LaTeX Document sample_report.zip

Pick one based on your skills and download the zip file.

Tip

Each zip contains a README.md and a TODO.md (both are plain text files) with further information and things to do respectively. For example in the README.md of sample_game.zip there are instructions on how to run the game.

1. Moving Into Version Control

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.

Get the Source and Intialize

  1. Unzip your chosen project somewhere. Hereinafter we will refer to the unzipped folder as your "project directory".

  2. Open a terminal in the directory of the project. To do so right click on the directory and then for Windows: Git Bash Here, MacOS: Services > New Terminal at Folder, Linux: you got this.

  3. Initialize a Git repository:

    $ git init  

    This will initialise a Git repository. If you enable hidden files in Windows Explorer (View > Hidden Items) or Finder (CMD + Shift + .) you will see that it has created a .git directory.

    Then you can also see that Git has no commits and is not tracking anything (yet) by reading the output of the command:

    $ git status

Move the Existing Code

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 such as Thumbs.db or .DS_Store), so we must tell git to ignore such files:

  1. Create an empty text file in the project directory called .gitignore (yes, it must start with a dot).

  2. Go to gitignore.io and in the box type what you are using, for example Windows, MacOS, Linux, Python or LaTeX, hit Create and copy the text generated by the website into the .gitignore file. Alternatively, you can also do this directly from the terminal:

    $ curl https://www.toptal.com/developers/gitignore/api/linux,macos,windows,python,latex > .gitignore

    You can also do it by hand (without the website), the syntax is not difficult to learn.

  3. 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 as Thumbs.db, .DS_Store, Report.aux. You can see git tells you

    use "git add <file>..." to include in what will be committed

    Recall the 3 (or 4) conceptual areas of Git

  4. Add the existing files or directories to the staging area using:

    $ git add .gitignore README.md TODO.md pyproject.toml snake # add all files

    Adding directories will recursively add all files within them. Alternatively a shorter command if you want to add all files at once is:

    $ git add --all

Caution

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..

Warning

If you are using sample_game.zip and have ran the game, do not add the venv directory because it contains a lot of files that are not directly part of your project. If you have accidentally added it e.g. using git add --all (though this should not have happened if .gitignore was configured correctly) reset your staging area by running:

$ git reset # remove everything from the staging area

and then add the files again more carefully.

  1. Run again

    $ git status
    

    Now you will see the files have turned green, they are in the staging area and git says Changes to be committed: above them.

  2. If the list of file looks good you can create your first commit with

    $ git commit

    Commit your changes

    This will open your editor of choice. 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

     [master (root-commit) 132f122] Move into version control
      7 files changed, 962 insertions(+)
      create mode 100644 .gitignore
      create mode 100644 README.md
      create mode 100644 TODO.md
      create mode 100644 pyproject.toml
      create mode 100644 snake/__main__.py
      create mode 100644 snake/game.py     
    

You have successfully created your first commit in the master branch (the default branch name used by Git).

2. Using Git Services to Collaborate

Register and Authenticate to a Git Service

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:

  1. 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 "your_email@example.com" # replace with your email

    This will generate an SSH key pair using elliptic curve cryptography.

  2. 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
  3. Copy your public key which should look something like this

    ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPLVAByZGT6xWM2kg7AeEkXbujOETnHdw2FOUx3/mpow your_email@example.com
    
  4. On your GitHub profile in the browser click your profile icon in the top right and go to Settings > SSH and GPG Keys > New SSH Key and paste your public key, leave the key type settings to an Authentication Key.

You will now be able to authenticate your computer with GitHub.

Upload the Project to the Git server (Remote)

The person that has done all of the steps so far (in part 1) needs to create a remote repository on their GitHub profile.

  1. Go to github.com/new and create a new repository. Set the name to gitws25. Leave it to public, do not pick any templates and hit Create Repository.

    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 the instruction under "... or push an existing repository from the command line". Before following the instructions make sure that in the blue shaded area you have selected SSH

  2. In your terminal you can add the remote with

    $ git remote add origin git@github.com: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, like github instead of origin (note that for the rest of this tutorial we will use origin, you can use a different name but you will need to update the next command accordingly). You can then check that Git has saved the remote by reading the output of

    $ git remote --verbose # show remote url
  3. Now we can push our first commit to origin with

    $ git push --set-upstream origin master

    The --set-upstream flag will set origin to be the default remote to push to. After setting this once you will be able to write just git push, and it will push to origin.

  4. Now, if you refresh the browser you should see that your file have been uploaded to GitHub.

3. Collaborate with Your Team

Use a Git server to bypass NAT and collaborate with others.

Cloning the project

The other members can finally do something. Hopefully they are not drunk yet.

  1. 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.

  2. The other members can see on their email inbox or at github.com/notifications an invitation to join the project. Accept the invitation.

  3. 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 git@github.com:YOUR_TEAM_MEMBER/gitws25.git # replace with your remote URL

Fast-forward merge

We will finally start to do something interesting with the Git commit graph. First we do a fast-forward merge, we need two people Alice and Bob. You can choose who plays which character. To make it interesting for the group, we will work with remote branches, even though the theory is the same for local branches.

  1. Alice: In the project folder there is a file TODO.md 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 under Changes not staged for commit: ... in the output of

    alice $ git status 

    You can quickly add the files you have changed with the staging area using the --update flag:

    alice $ git add --update # 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.

  1. 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.

True Merge (3-way-merge)

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).

  1. Alice and Bob: Pick any task from TODO.md 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
  2. 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.

  1. 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!
  1. Bob: Push the newly created merge commit to the remote origin

    bob $ git push origin master
  2. 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.

  1. Alice and Bob: Pick the same task from TODO.md 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.

  2. Alice: Push your changes to the remote.

  3. 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 with the merge conflict 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 terminal

    bob $ git status

    You will see that you are in the middle of a merge You have unmerged paths., and Git will tell you which files caused the merge conflict under Unmerged paths:.

  4. 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.

  1. Bob: Push your changes to remote

  2. Alice: Fetch and merge (pull) Bob’s changes. The two machines should be in sync.

Rebase

We will now repeat this process again but instead of merging we will use rebase. This is typical if you work in a team that wants to have a linear history or simplify pull requests (more on them later). To make it more interesting we will also start to use local branches.

  1. Alice: Pick any task from TODO.md and do it. Add your changes to the staging area and commit:

    alice $ git add ... # add the files you changes
    alice $ git commit  # with a good commit message

    Bob: Do the same but on a local branch feature-x. To create a new local branch from your local master (which is one commit behind Alice’s):

    bob $ git branch feature-x master # create a new branch feature-x from master
    bob $ git switch feature-x # move your HEAD to feature-x

    Then pick a different task from Alice (to avoid conflicts for now), make your changes and commit them

    alice $ git add ... # add the files you changes
    alice $ git commit  # with a good commit message
  2. Alice: Upload your changes to the remote repository

    alice $ git push origin master
  3. Bob: Fetch alice’s change and rebase your changes on top

    bob $ git fetch origin
    bob $ git rebase master

Feature Branches

Note

This subsection is about software development and project management. You can skip to the next part if you are not interested in the topic.

Install a Graphical Interface to Git

Now that you have gone through the pain of understanding Git at its lowest level using the command line, you may optionally install a graphical interface that hides away all of these details. I suggest Sublime Merge.

4. Collaborate with other Teams

Collaborate with other teams using a pull-request

Forking a project

Remote branches are confusing.

Create a Pull-Request