Git

Git

version control system

mainly helps with two categories of tasks:

  • keeping track of changes to a codebase
  • collaborating with other developers

Example repositories

Commits and branches

Commits

In git a commit is a snapshot of a codebase

The evolution of a codebase is represented by a sequence / tree of commits

Sometimes the term commit also refers to the transition / change from one snapshot to the next

Commits

simple commit log with one branch (main):

* add footer (main)
* add company logo
* add sidebar
* add placeholder content
* initialize website

Branches

branches allow development to happen on different tasks in parallel

The default branch is usually called main or master

In git a branch is a pointer to a specific commit

Commits and branches

commit log with one active feature branch:

* add sidebar (main)
| * correct typo in footer (footer)
| * add logo to footer
| * add footer with basic content
|/
* add placeholder content
* initialize website

Commits and branches

combining branches (via merge):

* merge branch 'footer' into main (main)
|\
| * correct typo in footer (footer)
| * add logo to footer
| * add footer with basic content
* | add sidebar
|/
* add placeholder content
* initialize website

Commits and branches

combining branches (via rebase and squash):

* add footer (main)
* add sidebar
* add placeholder content
* initialize website

User interfaces

User interfaces

  • command-line interface (default, big functionality)
  • graphical user interfaces
    • git gui and gitk
    • ...
  • web interfaces / hosted git repositories
    • GitHub
    • GitLab

Setup

Setting up git on Windows

Install from https://git-scm.com

Setting up git on Windows

recommendations:

select components: uncheck Windows Explorer integration (this would add new entries in the right-click menu of the explorer)

default editor: choose Nano as a simple console based text editor

name of the initial branch: choose "main"

line ending conversions: Checkout as-is, commit as-is - and set up your development environment to use LF

default behavior of git pull: only ever fast-forward

Configuring git

git config --global user.name "John Doe"
git config --global user.email johndoe@example.com
git config --global pull.ff true

Creating or cloning a git repository

Commands

  • git init
  • git clone

Creating a git repository

creating a new repository in a local folder:

git init

Cloning a git repository

cloning a public repository (from GitHub):

git clone https://github.com/libgit2/libgit2

creates a new folder libgit2 with the current state and all of the history

Recording changes

Commands

  • git status
  • git diff
  • git add
  • git restore
  • git commit

Commands

git status

prints information about the current state of the repository

Review changes to files since the last commit

view status of files (added / changed / deleted since last commit):

git status

view added / removed lines in files:

git diff

Staging

preparing all changed / added / removed HTML files for committing (staging files):

git add *.html

preparing all files:

git add .

Unstaging and undoing active changes

unstaging previously staged files:

git restore --staged readme.txt

discarding unstaged changes:

git restore readme.txt

Committing

making a commit of everything that has changed and providing a commit message:

git add .
git commit -m "changing some HTML files"

Committing

compact version for staging and committing all changes:

git commit -a -m "changing some HTML files"

Ignoring files

We can list files to ignore in a special text file called .gitignore (without a filename extension):

__pycache__
node_modules
.vscode

History

Commands

  • git log
  • git show
  • git diff
  • git checkout
  • git revert

History

list past commits:

git log
git log --oneline
git log --oneline --graph
git log --oneline --graph --all

example output of the second command:

* e84890f (HEAD -> main, origin/main, origin/HEAD) add footer
* 9eb2f53 add company logo
* 5c41c01 add sidebar
* f4f591c add placeholder content
* d6510c2 initialize website

History

view changes between 19e0e64... and its parent commit:

git show 19e0

view changes between 19e0e64... and the current state:

git diff 19e0

short output:

git diff 19e0 --name-status

History

accessing the contents of an earlier commit (whose id is b4c906...):

git checkout . b4c9

going back to the most recent commit of the main branch:

git switch main

History

reverting the latest commit (via a new commit):

git revert HEAD

Feature branch workflow

Feature branch workflow

workflow:

To introduce a new feature / change, create a new so-called feature branch

The feature branch can individually evolve in parallel to the main branch

If the main branch evolves, its changes can be combined / merged back into the feature branch

Once the feature is complete, it can be combined / merged back into the main branch (after being reviewed by other developers)

Feature branch workflow

often feature branches can be small, e.g. fix-spelling-error-in-readme

some feature branches must be big, e.g. port-to-typescript

Feature branch workflow

after being combined / merged back into the main branch, feature branches are usually deleted

Feature branch workflow

example: developers are working on two different tasks at the same time:

* add sidebar (sidebar)
| * add logo to footer (footer)
| * add footer with basic content
|/
* add placeholder content (main)
* initialize website

Feature branch workflow

when a feature is completed it can be combined / merged back into the main branch:

* merge branches (main)
|\
* | add sidebar
| * add logo to footer
| * add footer with basic content
|/
* add placeholder content
* initialize website

old feature branches are usually deleted

Feature branch workflow

during development:

  • create a new feature branch off of main
  • commit to it often
  • merge (or rebase) when new commits are made to the main branch to keep up with the rest of the project

when the feature is ready:

  • optional: combine all commits on the branch into one commit (rebase)
  • merge into the main branch
  • delete the feature branch

See also

Creating and switching branches

Commands

  • git branch foo
  • git branch foo $commitid
  • git switch foo
  • git switch -c bar
  • git switch -c bar $commitid
  • git branch

Creating a branch

git branch python-3-port

Switching branches

Switching between python-3-port and main:

git switch python-3-port
git switch main

Switching branches

before switching it can be useful to make sure there are no active changes

git status
git switch main

Creating and switching in one

git switch -c python-3-port

create and switch to a new branch

Listing branches

listing all (local) branches:

git branch

Combining branches

Combining branches

strategies:

  • merge: simplest, keeps all commits from the feature branch (creates complex histories)
  • squash and merge: combines all commits on the feature branch into a single commit
  • rebase: most complex, uses only selected commits

Combining branches via merge

Combining branches via merge

example commit history (during feature development):

  * merge branches (footer)
 /|
* | add company logo (main)
| * add copyright notice to footer
| * merge branch 'main' into 'footer'
|/|
* | add sidebar
| * add logo to footer
| * add footer with basic content
|/
* add placeholder content
* initialize website

Combining branches via merge

example commit history (when feature is complete):

* merge branches (main)
|\
* | add company logo
| * add copyright notice to footer
| * merge branch 'main' into 'footer'
|/|
* | add sidebar
| * add logo to footer
| * add footer with basic content
|/
* add placeholder content
* initialize website

Combining branches via merge

commands for merging changes of main into footer:

git switch footer
git merge main

Merge conflicts

if two branches changed the same line in different ways there may be a merge conflict

Merge conflicts

presentation of a merge conflict in a file:

First line
Second line
<<<<<< HEAD
Thrd line!
======
Third line
>>>>>> main
Fourth line

one branch added an exclamation mark, another one fixed a spelling error

Resolving merge conflicts

  • edit the file and keep the desired changes
  • add the files with resolved conflicts
  • run git commit (without extra arguments)

Deleting old branches

we will usually delete a branch once it is merged:

deleting a merged branch:

git branch -d footer

deleting an unmerged branch:

git branch -D footer

Exercises

Exercises

  • todo list
  • work on an existing project from GitHub (e.g. on the readme)

Exercises

create a text file with some todos:

- groceries
- taxes
x gardening

modify the todo list via separate feature branches, e.g. "long-term todos", "new-job", "new-job-sub-items", "taxes-completed", ...

Git remote

Git remote

Hosts for Git:

  • GitHub
  • GitLab

Collaboration via GitHub

initial options:

  • clone an existing git repository from GitHub
  • publish local repository to GitHub

Cloning an existing Git repository

git clone https://github.com/...

On GitHub, copy the link from the green clone or download button

Publishing a new Git repository

On GitHub, click the + in the top right corner

Don't select "Initialize this repository with a README".

Publishing a new Git repository

Once you have an empty repository on GitHub, follow the instructions for an existing repository displayed on GitHub

Usually you will connect a local repository to a single remote repository - the remote repository is conventionally named origin

git remote add origin https://github.com/...

Publishing a new branch

Whenever we want to publish a branch the remote doesn't know about:

git push -u origin main

The above command copies the the commits in the local main branch to a newly created remote main branch.

Publishing commits to a known branch

If we want to publish commits to a known branch:

git push

Getting new commits from a remote branch

Fetch and merge commits from the remote branch corresponding to the active branch:

git pull

Deleting a remote branch

deleting a local branch:

git branch -d python-3-port

deleting the remote branch as well:

git push origin :python-3-port

Remembering credentials

git config credential.helper cache

Git will now remember passwords for 15 minutes

Editing history via rebase

Editing history

In git it is possible to edit history - but it comes with dangers

Editing history

example use cases:

  • restructure commits in a branch to make them clearer
  • undo a commit that was made by mistake

Editing history

rules:

  • don't change history of branches that others may branch off of (e.g. main)
  • you may change history of your own repository

Editing history via rebase

original commit log:

  * merge branch 'main' into 'footer' (footer)
 /|
* | add company logo (main)
| * add copyright notice to footer
| * merge branch 'main' into 'footer'
|/|
* | add sidebar
| * add logo to footer
| * add footer with basic content
|/
* add placeholder content
* initialize website

Editing history via rebase

new commit log:

  * add footer (footer)
 /
* add company logo (main)
* add sidebar
* add placeholder content
* initialize website

note: the main branch was not modified

Editing history via rebase

editing history via rebase in git:

git rebase -i main

interactively edit the current branch from the point where it branched off of main

Editing history via rebase

squashing commits:

change all except the first commands from pick to squash

Aliases and Extras

Aliases and Extras

  • aliases: custom short names for commands
  • git-extras: package of useful aliases and extra commands

Aliases

creating some aliases:

git config --global alias.unstage 'restore --staged'
git config --global alias.show-tree 'log --graph --oneline --all'

Extras

git-extras provides simplified commands for common tasks

  • git ignore
  • git show-tree
  • git squash
  • git undo

https://github.com/tj/git-extras/blob/master/Commands.md