Floris van den Bosch
February 26, 2024
manage changes made to collections of information
Examples
All version of your project are on your local PC
All versions are on a server
Easy to manage, but has a single point of failure
Everyone has a copy of the project.
This allows for more flexible setups.
git init
This creates the .git
subdirectory that stores all
versions
We now have a git repository!
We create a new game based on werewolves and quantum mechanics
$ mkdir quantumwerewolf
$ cd quantumwerewolf
$ git init
git clone <project-url>
The project is copied into the current directory
We clone a game about werewolves and quantum mechanics
$ git clone https://github.com/ProodjePindakaas/Quantum-Werewolf.git
$ cd quantumwerewolf
We now have made a change, but git has not recorded it yet
We need to tell git which changes to record with
git add <file>
These changes are now staged
Now the file is ready to be committed
This will permanently add the changes to the file history
git commit
This will your text editor where you can describe the changes in this commit in detail.
Or short description with the -m
option
git commit -m "Fixed the bug"
git status
View the current state of all files
$ git status
On branch main
Your branch is up to date with 'origin/main'.
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
modified: staged_file.txt
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: modified_file.txt
Untracked files:
(use "git add <file>..." to include in what will be committed)
new_file.txt
See what you modified but have not staged with
$ git diff
Or see what you have staged but not committed
$ git diff --staged
diff --git a/quantumwerewolf/cli.py b/quantumwerewolf/cli.py
index 6cfa32f..1a38216 100644
--- a/quantumwerewolf/cli.py
+++ b/quantumwerewolf/cli.py
@@ -70,7 +70,7 @@ class CliGame(Game):
def ask_player(self, query, invalid_players=[]):
answer = input(query + 'Name: ')
- if answer.isdigit():
+ if answer.isdecimal():
i = int(answer) - 1
if i in range(self.player_count):
answer = self.players[i]
git log
Get a summary of the commit history
$ git log
commit 5658af2ab70472d25bb47cf6a62468ec0b966ed3 (main)
Author: Floris van den Bosch <f.vdbosch98@gmail.com>
Date: Wed Feb 28 11:06:31 2024 +0100
Fixed the bug
git init
git clone
git add
git commit
git status
git diff
git log
Without branching our project history looks like this
Note: the default branch may also be called
main
git branch <branch-name>
this creates a new branch with the name
<branch-name>
Usually branches are created for a specific purpose
We can check out the new branch
git checkout <branch-name>
Moves the HEAD to this branch and changes our local files accordingly.
We create new branch for the bug
$ git branch iss53
$ git checkout iss53
With git status
we can see on which branch we are
$ git status
On branch iss53
Now we make the changes as before and commit them with
git commit
When a branch is done and tested we want to merge it into the main branch
git checkout <master-branch>
git merge <branch-to-merge>
When all is we and tested we merge the fix for the issue.
$ git checkout master
$ git merge iss53
Updating f42c576..3a0874c
Fast-forward
quantumwerewolf/cli.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
This we call a fast-forward, as the history is still linear
We are working on two branches
first we merge the hotfix into master
This is a simple fast-forward
The hotfix
branch can now be deleted
Finally, when the iss53
branch is done we merge this
into the master
branch
If we alter the same line in the same file, we get a conflict
When a conflict occurs git does not make a new commit
$ git merge iss53
Auto-merging example.txt
CONFLICT (content): Merge conflict in quantumwerewolf/cli.py
Automatic merge failed; fix conflicts and then commit the result.
git mergetool
This detects the conflict and lets you fix them in your favorite mergetool (e.g. vimdiff)
After the manual merging we still need to commit the merge.
git rebase <rebase-to-branch>
An alternative to a merge (or fast-forward) is the rebase
It fast-forwards the branching point of the branch
Best practice: avoid using rebases
We have a simple divergence
We could do a regular merge
$ git checkout master
$ git merge experiment
Instead, we rebase the experiment
to the
master
branch
$ git checkout experiment
$ git rebase master
Now we move the master
branch forward again
$ git checkout master
$ git merge experiment
A remote is a copy of the project’s repository in another location
Examples
Note: Using git clone
automatically adds the remote
origin
git remote
This shows a list of current remotes
git remote -v
This shows the URLs for each remote
$ git clone https://github.com/ProodjePindakaas/Quantum-Werewolf.git
$ cd quantumwerewolf
$ git remote
origin
$ git remote -v
origin https://github.com/ProodjePindakaas/Quantum-Werewolf.git (fetch)
origin https://github.com/ProodjePindakaas/Quantum-Werewolf.git (push)
git fetch <remote>
Gets the history on your remote
git push <remote> <branch>
Sends and add your changes to the remote
git pull <remote> <branch>
Retrieves and merges changes from the remote
Sending the bugfix to the remote (Github)
$ git push -u origin iss53
Note: -u
is needed as the iss53
branch
does not exist yet on the remote
Or get the fix from the remote
$ git pull origin iss53
Note: this might be one situation to use rebase if you haven’t pulled from the remote in a long while.
git remote add <name> <url>
Adds a new remote
We want to run the game on a cluster
me@cluster $ git clone me@host:/path/to/repository
me@host $ git remote add cluster me@cluster:/path/to/copy
Now we can push our program to the cluster!
self-hosting options:
Local files that you do not want to record:
Declare files/folders you want git to ignore in
.gitignore
files
Hint: you can find premade .gitignore
files in github.com/github/gitignore
for many programming languages
By default, git gives every version (commit) a hash to identify it
git tag <version>
Allows you to manually tag the current version (ex.
git tag v3.1.4
)
You can also tag a previous commit with its hash
git tag <version> <hash>
We all make mistakes
git stash
Temporarily store your file modifications
git stash pop
Applies the stored changes to your current branch
The git log
command shows a linear history by
default
git log --oneline --graph --color --all --decorate
Shows the branches explicitly as ‘timelines’
You can alias command and options you often use
git config alias.<alias-name> <command>
such as
git config --global alias.tree 'log --oneline --graph --color --all --decorate'
Now we can just run git tree
!
You may run into the same conflict numerous times
git config --global rerere.enabled true
Enabling ReReRe (Reuse Recorded Resolution) automatically applied your conflict resolutions to future occurences
Inspired by and images from Chacon, S., & Straub, B. Pro Git (Version 2)
https://github.com/progit/progit2