Compare commits
6 Commits
f17b9ef0f6
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| b7b627d1fe | |||
| 068a83b183 | |||
| a4848b9972 | |||
| dfce75c068 | |||
| 7b909ae4da | |||
| 62360da2e5 |
+9
-137
@@ -1,9 +1,15 @@
|
||||
# ASCII table
|
||||
|
||||
Ascii table because websites are unusable these days
|
||||
Ascii table, because websites are unusable these days
|
||||
|
||||
|
||||
## regular ascii table
|
||||
> In `Bash` one can input any character by pressing `Ctrl+v` (= `^V`)
|
||||
> and then entering the code of the character.
|
||||
>
|
||||
> Example for ASCII in decimal: `^Vnnn`, where 0 <= nnn <= 255
|
||||
>
|
||||
> Example for ASCII in hex: `^Vxnn`, where 0 <= nn <= FF
|
||||
>
|
||||
> For Unicode do `^Vu<code>`, where 0 <= code <= FFFF
|
||||
|
||||
| **dec** | **hex** | **char** | **description** |
|
||||
|----------:|----------:|:----------|:------------------------------|
|
||||
@@ -135,137 +141,3 @@ Ascii table because websites are unusable these days
|
||||
| 125 | `0x7D` | } | right curly bracket |
|
||||
| 126 | `0x7E` | ~ | tilde |
|
||||
| 127 | `0x7F` | DEL | delete |
|
||||
|
||||
|
||||
## extended ascii table
|
||||
|
||||
| **dec** | **hex** | **char** | **description** |
|
||||
|----------:|----------:|:----------|:------------------------------|
|
||||
| 128 | `0x80` | Ç | majuscule c-cedilla |
|
||||
| 129 | `0x81` | ü | letter u with umlaut or diaeresis , u-umlaut |
|
||||
| 130 | `0x82` | é | letter e with acute accent or e-acute |
|
||||
| 131 | `0x83` | â | letter a with circumflex accent or a-circumflex |
|
||||
| 132 | `0x84` | ä | letter a with umlaut or diaeresis , a-umlaut |
|
||||
| 133 | `0x85` | à | letter a with grave accent |
|
||||
| 134 | `0x86` | å | letter a with a ring |
|
||||
| 135 | `0x87` | ç | minuscule c-cedilla |
|
||||
| 136 | `0x88` | ê | letter e with circumflex accent or e-circumflex |
|
||||
| 137 | `0x89` | ë | letter e with umlaut or diaeresis ; e-umlauts |
|
||||
| 138 | `0x8A` | è | letter e with grave accent |
|
||||
| 139 | `0x8B` | ï | letter i with umlaut or diaeresis ; i-umlaut |
|
||||
| 140 | `0x8C` | î | letter i with circumflex accent or i-circumflex |
|
||||
| 141 | `0x8D` | ì | letter i with grave accent |
|
||||
| 142 | `0x8E` | Ä | letter a with umlaut or diaeresis ; a-umlaut |
|
||||
| 143 | `0x8F` | Å | capital letter a with a ring |
|
||||
| 144 | `0x90` | É | capital letter e with acute accent or e-acute |
|
||||
| 145 | `0x91` | æ | latin diphthong ae in lowercase |
|
||||
| 146 | `0x92` | Æ | latin diphthong ae in uppercase |
|
||||
| 147 | `0x93` | ô | letter o with circumflex accent or o-circumflex |
|
||||
| 148 | `0x94` | ö | letter o with umlaut or diaeresis ; o-umlaut |
|
||||
| 149 | `0x95` | ò | letter o with grave accent |
|
||||
| 150 | `0x96` | û | letter u with circumflex accent or u-circumflex |
|
||||
| 151 | `0x97` | ù | letter u with grave accent |
|
||||
| 152 | `0x98` | ÿ | lowercase letter y with diaeresis |
|
||||
| 153 | `0x99` | Ö | letter o with umlaut or diaeresis ; o-umlaut |
|
||||
| 154 | `0x9A` | Ü | letter u with umlaut or diaeresis ; u-umlaut |
|
||||
| 155 | `0x9B` | ø | lowercase slashed zero or empty set |
|
||||
| 156 | `0x9C` | £ | pound sign ; symbol for the pound sterling |
|
||||
| 157 | `0x9D` | Ø | uppercase slashed zero or empty set |
|
||||
| 158 | `0x9E` | × | multiplication sign |
|
||||
| 159 | `0x9F` | ƒ | function sign ; f with hook sign ; florin sign |
|
||||
| 160 | `0xA0` | á | lowercase letter a with acute accent or a-acute |
|
||||
| 161 | `0xA1` | í | lowercase letter i with acute accent or i-acute |
|
||||
| 162 | `0xA2` | ó | lowercase letter o with acute accent or o-acute |
|
||||
| 163 | `0xA3` | ú | lowercase letter u with acute accent or u-acute |
|
||||
| 164 | `0xA4` | ñ | eñe, enie, spanish letter enye, lowercase n with tilde |
|
||||
| 165 | `0xA5` | Ñ | spanish letter enye, uppercase n with tilde, eñe, enie |
|
||||
| 166 | `0xA6` | ª | feminine ordinal indicator |
|
||||
| 167 | `0xA7` | º | masculine ordinal indicator |
|
||||
| 168 | `0xA8` | ¿ | inverted question marks |
|
||||
| 169 | `0xA9` | ® | registered trademark symbol |
|
||||
| 170 | `0xAA` | ¬ | logical negation symbol |
|
||||
| 171 | `0xAB` | ½ | one half |
|
||||
| 172 | `0xAC` | ¼ | quarter, one fourth |
|
||||
| 173 | `0xAD` | ¡ | inverted exclamation marks |
|
||||
| 174 | `0xAE` | « | angle quotes, guillemets, right-pointing quotation mark |
|
||||
| 175 | `0xAF` | » | guillemets, angle quotes, left-pointing quotation marks |
|
||||
| 176 | `0xB0` | ░ | graphic character, low density dotted |
|
||||
| 177 | `0xB1` | ▒ | graphic character, medium density dotted |
|
||||
| 178 | `0xB2` | ▓ | graphic character, high density dotted |
|
||||
| 179 | `0xB3` | │ | box drawing character single vertical line |
|
||||
| 180 | `0xB4` | ┤ | box drawing character single vertical and left line |
|
||||
| 181 | `0xB5` | Á | capital letter a with acute accent or a-acute |
|
||||
| 182 | `0xB6` | Â | letter a with circumflex accent or a-circumflex |
|
||||
| 183 | `0xB7` | À | letter a with grave accent |
|
||||
| 184 | `0xB8` | © | copyright symbol |
|
||||
| 185 | `0xB9` | ╣ | box drawing character double line vertical and left |
|
||||
| 186 | `0xBA` | ║ | box drawing character double vertical line |
|
||||
| 187 | `0xBB` | ╗ | box drawing character double line upper right corner |
|
||||
| 188 | `0xBC` | ╝ | box drawing character double line lower right corner |
|
||||
| 189 | `0xBD` | ¢ | cent symbol |
|
||||
| 190 | `0xBE` | ¥ | yen and yuan sign |
|
||||
| 191 | `0xBF` | ┐ | box drawing character single line upper right corner |
|
||||
| 192 | `0xC0` | └ | box drawing character single line lower left corner |
|
||||
| 193 | `0xC1` | ┴ | box drawing character single line horizontal and up |
|
||||
| 194 | `0xC2` | ┬ | box drawing character single line horizontal down |
|
||||
| 195 | `0xC3` | ├ | box drawing character single line vertical and right |
|
||||
| 196 | `0xC4` | ─ | box drawing character single horizontal line |
|
||||
| 197 | `0xC5` | ┼ | box drawing character single line horizontal vertical |
|
||||
| 198 | `0xC6` | ã | lowercase letter a with tilde or a-tilde |
|
||||
| 199 | `0xC7` | Ã | capital letter a with tilde or a-tilde |
|
||||
| 200 | `0xC8` | ╚ | box drawing character double line lower left corner |
|
||||
| 201 | `0xC9` | ╔ | box drawing character double line upper left corner |
|
||||
| 202 | `0xCA` | ╩ | box drawing character double line horizontal and up |
|
||||
| 203 | `0xCB` | ╦ | box drawing character double line horizontal down |
|
||||
| 204 | `0xCC` | ╠ | box drawing character double line vertical and right |
|
||||
| 205 | `0xCD` | ═ | box drawing character double horizontal line |
|
||||
| 206 | `0xCE` | ╬ | box drawing character double line horizontal vertical |
|
||||
| 207 | `0xCF` | ¤ | generic currency sign |
|
||||
| 208 | `0xD0` | ð | lowercase letter eth |
|
||||
| 209 | `0xD1` | Ð | capital letter eth |
|
||||
| 210 | `0xD2` | Ê | letter e with circumflex accent or e-circumflex |
|
||||
| 211 | `0xD3` | Ë | letter e with umlaut or diaeresis, e-umlaut |
|
||||
| 212 | `0xD4` | È | capital letter e with grave accent |
|
||||
| 213 | `0xD5` | ı | lowercase dot less i |
|
||||
| 214 | `0xD6` | Í | capital letter i with acute accent or i-acute |
|
||||
| 215 | `0xD7` | Î | letter i with circumflex accent or i-circumflex |
|
||||
| 216 | `0xD8` | Ï | letter i with umlaut or diaeresis ; i-umlaut |
|
||||
| 217 | `0xD9` | ┘ | box drawing character single line lower right corner |
|
||||
| 218 | `0xDA` | ┌ | box drawing character single line upper left corner |
|
||||
| 219 | `0xDB` | █ | block, graphic character |
|
||||
| 220 | `0xDC` | ▄ | bottom half block |
|
||||
| 221 | `0xDD` | ¦ | vertical broken bar |
|
||||
| 222 | `0xDE` | Ì | capital letter i with grave accent |
|
||||
| 223 | `0xDF` | ▀ | top half block |
|
||||
| 224 | `0xE0` | Ó | capital letter o with acute accent or o-acute |
|
||||
| 225 | `0xE1` | ß | letter eszett ; scharfes s or sharp s |
|
||||
| 226 | `0xE2` | Ô | letter o with circumflex accent or o-circumflex |
|
||||
| 227 | `0xE3` | Ò | capital letter o with grave accent |
|
||||
| 228 | `0xE4` | õ | lowercase letter o with tilde or o-tilde |
|
||||
| 229 | `0xE5` | Õ | capital letter o with tilde or o-tilde |
|
||||
| 230 | `0xE6` | µ | lowercase letter mu ; micro sign or micron |
|
||||
| 231 | `0xE7` | þ | lowercase letter thorn |
|
||||
| 232 | `0xE8` | Þ | capital letter thorn |
|
||||
| 233 | `0xE9` | Ú | capital letter u with acute accent or u-acute |
|
||||
| 234 | `0xEA` | Û | letter u with circumflex accent or u-circumflex |
|
||||
| 235 | `0xEB` | Ù | capital letter u with grave accent |
|
||||
| 236 | `0xEC` | ý | lowercase letter y with acute accent |
|
||||
| 237 | `0xED` | Ý | capital letter y with acute accent |
|
||||
| 238 | `0xEE` | ¯ | macron symbol |
|
||||
| 239 | `0xEF` | ´ | acute accent |
|
||||
| 240 | `0xF0` | ≡ | congruence relation symbol |
|
||||
| 241 | `0xF1` | ± | plus-minus sign |
|
||||
| 242 | `0xF2` | ‗ | underline or underscore |
|
||||
| 243 | `0xF3` | ¾ | three quarters, three-fourths |
|
||||
| 244 | `0xF4` | ¶ | paragraph sign or pilcrow ; end paragraph mark |
|
||||
| 245 | `0xF5` | § | section sign |
|
||||
| 246 | `0xF6` | ÷ | the division sign ; obelus |
|
||||
| 247 | `0xF7` | ¸ | cedilla |
|
||||
| 248 | `0xF8` | ° | degree symbol |
|
||||
| 249 | `0xF9` | ¨ | diaresis |
|
||||
| 250 | `0xFA` | · | interpunct or space dot |
|
||||
| 251 | `0xFB` | ¹ | superscript one, exponent 1, first power |
|
||||
| 252 | `0xFC` | ³ | superscript three, exponent 3, cube, third power |
|
||||
| 253 | `0xFD` | ² | superscript two, exponent 2, square, second power |
|
||||
| 254 | `0xFE` | ■ | black square |
|
||||
| 255 | `0xFF` | nbsp | non-breaking space or no-break space |
|
||||
|
||||
@@ -21,7 +21,7 @@ DEVICE := STM32H573II
|
||||
# include c sources list
|
||||
AS_SOURCES :=
|
||||
C_SOURCES :=
|
||||
include ./src.mk
|
||||
include ./sources.mk
|
||||
|
||||
# compiler commands
|
||||
PREFIX := arm-none-eabi-
|
||||
@@ -93,6 +93,13 @@ To reset the program one can use the following command
|
||||
monitor reset halt
|
||||
```
|
||||
|
||||
|
||||
## breakpoints
|
||||
|
||||
To set breakpoints use the command `b`.
|
||||
<!-- TODO: elaborate on breakpoint (conditions, etc.) -->
|
||||
|
||||
|
||||
## TUI mode
|
||||
|
||||
The `GDB` comes with a Terminal User Interface (TUI) which provides view for
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
SHELL := /usr/bin/env bash
|
||||
|
||||
MD_FILES += readme.md
|
||||
|
||||
PDF_FILES := $(MD_FILES:.md=.pdf)
|
||||
|
||||
VERBOSITY :=
|
||||
|
||||
|
||||
.PHONY: all clean clean_all test pdf repdf remove_pdf debug_pdf gfm
|
||||
|
||||
|
||||
clean_all:: remove_pdf
|
||||
|
||||
|
||||
pdf: $(PDF_FILES)
|
||||
|
||||
|
||||
repdf: remove_pdf pdf
|
||||
|
||||
|
||||
remove_pdf:
|
||||
@rm -f $(PDF_FILES) || true
|
||||
|
||||
|
||||
debug_pdf: VERBOSITY := --verbose
|
||||
debug_pdf: $(PDF_FILES)
|
||||
|
||||
|
||||
%.pdf: %.md
|
||||
pandoc \
|
||||
--pdf-engine pdflatex \
|
||||
--listings \
|
||||
--template ../template.tex \
|
||||
-f markdown \
|
||||
-t pdf \
|
||||
$(VERBOSITY) \
|
||||
-o $@ \
|
||||
$<
|
||||
@@ -0,0 +1,752 @@
|
||||
# Git Gud (at Git)
|
||||
|
||||
This document shall serve as both kickstart and quick reference for
|
||||
beginners.
|
||||
Though even experienced users may learn something new.
|
||||
|
||||
> For a more complete instructions have a look at [**Pro Git**][progit].
|
||||
> You can access the book either as HTML document, PDF or EPUB.
|
||||
> Change the websites language for localised versions of the book.
|
||||
|
||||
|
||||
## Table of contents
|
||||
|
||||
<!--toc:start-->
|
||||
- [Git Gud (at Git)](#git-gud-at-git)
|
||||
- [Table of contents](#table-of-contents)
|
||||
- [Terminology](#terminology)
|
||||
- [Git & Github](#git-github)
|
||||
- [Git help](#git-help)
|
||||
- [Configuration](#configuration)
|
||||
- [Creating a repository](#creating-a-repository)
|
||||
- [The concept of commits](#the-concept-of-commits)
|
||||
- [Creating a commit](#creating-a-commit)
|
||||
- [.gitignore files](#gitignore-files)
|
||||
- [Branches](#branches)
|
||||
- [Creating/switching a branch](#creatingswitching-a-branch)
|
||||
- [Merging/rebasing a branch](#mergingrebasing-a-branch)
|
||||
- [*Merge* or *rebase*?](#merge-or-rebase)
|
||||
- [Merging](#merging)
|
||||
- [Rebasing](#rebasing)
|
||||
- [Resolving conflicts](#resolving-conflicts)
|
||||
- [History inspection](#history-inspection)
|
||||
- [History rewriting](#history-rewriting)
|
||||
- [Troubleshooting](#troubleshooting)
|
||||
- [I lost a commit!](#i-lost-a-commit)
|
||||
- [I tried to pull, but got a merge conflict?!](#i-tried-to-pull-but-got-a-merge-conflict)
|
||||
- [Further reading](#further-reading)
|
||||
- [Glossary](#glossary)
|
||||
<!--toc:end-->
|
||||
|
||||
|
||||
## Terminology
|
||||
|
||||
Command examples may have arguments enclosed with angled brackets
|
||||
(`<>`).
|
||||
That means the user needs to substitute the argument with their
|
||||
value.
|
||||
The text inside the angled brackets describes the expected value.
|
||||
|
||||
Additionally an argument may be enclosed by brackets (`[]`).
|
||||
That means the argument is optional.
|
||||
|
||||
|
||||
## Git & Github
|
||||
|
||||
Some might be confused about Git and Github
|
||||
They have similar names, with Github just adding a 'hub'.
|
||||
|
||||
* **Git** is a version control system, that lets you save, analyse and
|
||||
edit the history of files.
|
||||
It can be used locally, or in combination with a server.
|
||||
The latter allows for collaboration with a team and can act as backup.
|
||||
Git is licensed under GPLv2.
|
||||
* **Github** is a frontend for Git, which adds functions like a
|
||||
webserver, access control, pull requests or issues to name a few.
|
||||
It is not a usable service on its own.
|
||||
Github is proprietary and owned by Microsoft since 2018.
|
||||
|
||||
|
||||
## Git help
|
||||
|
||||
When unsure about a Git (sub)command append `--help`.
|
||||
This opens the most specific manual available for your command.
|
||||
|
||||
Example:
|
||||
|
||||
```sh
|
||||
# show help for the 'config' subcommand
|
||||
git config --help
|
||||
|
||||
# show help for the 'remote add' subcommand
|
||||
git remote add --help
|
||||
```
|
||||
|
||||
|
||||
## Configuration
|
||||
|
||||
Before starting to use Git it is recommended to configure the user
|
||||
name and email at the very least.
|
||||
Otherwise, Git will ask you at the first action which requires an
|
||||
identity, most probably `push`.
|
||||
|
||||
Git looks for a file `~/.gitconfig` (`~` = users home directory).
|
||||
You can either (create and) edit the file directly, or use
|
||||
`git config`.
|
||||
See the example below for how to configure the user name and mail.
|
||||
|
||||
```
|
||||
[user]
|
||||
name = student
|
||||
email = student@students.zhaw.ch
|
||||
```
|
||||
|
||||
Alternatively use the following commands to let Git write the
|
||||
configuration file.
|
||||
|
||||
```sh
|
||||
git config set user.name <you-display-name>
|
||||
git config set user.email <your-address@domain.global-domain>
|
||||
```
|
||||
|
||||
> For Linux users keeping their configuration files in a repository,
|
||||
> distributing them with symbolic links, the Git configuration can
|
||||
> include files.
|
||||
> So the user and email can be stored in a separate file.
|
||||
>
|
||||
> ```
|
||||
> [include]
|
||||
> path = /path/to/include/file
|
||||
> ```
|
||||
|
||||
Sensible options to set are the editor used for commit messages,
|
||||
the default branch name and whether to merge or rebase.
|
||||
The value of editor is the launch command of the desired editor.
|
||||
Below is an excerpt from my configuration as an example.
|
||||
|
||||
```git
|
||||
[core]
|
||||
editor = nvim
|
||||
|
||||
[init]
|
||||
defaultBranch = main
|
||||
|
||||
[pull]
|
||||
rebase = true
|
||||
```
|
||||
|
||||
|
||||
## Creating a repository
|
||||
|
||||
When working with a Git frontend like Github there are two ways to
|
||||
start a repository:
|
||||
|
||||
* **Local:** Use `git init` to initialise the current directory as
|
||||
a Git repository. This will create a directory `.git` which contains
|
||||
the local information, e.g. history, commit hashes, hooks, etc.
|
||||
If you want to synchronise a local repository with a server, follow
|
||||
the steps for creating a remote repository and use `git remote add`
|
||||
to add a remote and its URL (default remote name is `origin`).
|
||||
* **Remote:** Open the frontend of choice and create a new repository.
|
||||
On Github there is usually a green button in the top right corner.
|
||||
Choose a name, description and licence.
|
||||
Now get the URL to clone the repository locally, or set it as remote
|
||||
in an existing one.
|
||||
On Github click the green `Code` button and choose either **https**
|
||||
or **ssh** (recommended, but requires additional setup).
|
||||
|
||||
See examples for the Git commands mentioned in this section below.
|
||||
|
||||
```sh
|
||||
# initialise directory as git repository
|
||||
# use '.' as path to initialise current directory
|
||||
git init [<path/to/directory>]
|
||||
|
||||
# add remote to local repository under name 'origin'
|
||||
git remote add origin <url-to-remote-repository>
|
||||
|
||||
# change URL, for example to switch to ssh after cloning
|
||||
# a repository over https
|
||||
git remote set-url <remote-name> <remote-url>
|
||||
|
||||
# clone a remote repository
|
||||
git clone <repository-url>
|
||||
```
|
||||
|
||||
> Mind, that a remote is not strictly necessary, because the local
|
||||
> repository contains the full information for version control.
|
||||
> A remote is useful as a backup of your information and to work with
|
||||
> other contributors.
|
||||
|
||||
> Choosing a licence is important, if only to deny liability for
|
||||
> your code.
|
||||
|
||||
> I recommend to setup a pair of ssh keys and use ssh connections
|
||||
> to interact with the Git server.
|
||||
> It is more secure and usually more convenient too.
|
||||
|
||||
|
||||
## The concept of commits
|
||||
|
||||
Before looking at how to add or change commits, it is prudent to get
|
||||
an understanding of what a commit is.
|
||||
|
||||
A Git history is a linked list of changes, called commits.
|
||||
Each commit has one (or in case of merge commits more) parents and an
|
||||
arbitrary number of children.
|
||||
A commit is a delta relative to its parent(s) and does **not**
|
||||
directly contain the current state.
|
||||
|
||||
|
||||
## Creating a commit
|
||||
|
||||
Use `git add <file-or-directory>` to stage changes made to a file
|
||||
or directory (a directory means all contained files, recursively).
|
||||
List the changed files in your working tree with `git status` and show
|
||||
the differences with `git diff [<path>]`.
|
||||
|
||||
With `git commit` you can commit the staged changes.
|
||||
This will open the configured editor.
|
||||
Enter your commit message at the very top, save and close the file.
|
||||
|
||||
```
|
||||
|
||||
# Please enter the commit message for your changes. Lines starting
|
||||
# with '#' will be ignored, and an empty message aborts the commit.
|
||||
#
|
||||
# On branch main
|
||||
# Your branch is up to date with 'origin/main'.
|
||||
#
|
||||
# Changes to be committed:
|
||||
# modified: git-introduction/readme.md
|
||||
#
|
||||
```
|
||||
|
||||
You now created a commit, but it is only local, use `git push` to
|
||||
upload it to the remote repository
|
||||
(This may fail due to conflicts, see
|
||||
[Resolving conflicts][conflicts]).
|
||||
|
||||
Instead of opening an editor you can also commit with
|
||||
`git commit -m <commit-message>` but I prefer opening an editor,
|
||||
because it gives me another chance to spot missing changes, or changes
|
||||
I did not want to add to the commit.
|
||||
|
||||
> It is sensible to make small commits with coherent scope.
|
||||
>
|
||||
> When adding a source file it is reasonable to commit the change to
|
||||
> the Makefile too.
|
||||
>
|
||||
> However committing two code changes for distinct functionality at
|
||||
> once is frown upon.
|
||||
>
|
||||
> The reason is, that when searching the history for a commit, it gets
|
||||
> really difficult to find the change you are looking for, when
|
||||
> commits contain a lot of changes.
|
||||
|
||||
|
||||
## .gitignore files
|
||||
|
||||
Committing files generated by the project is a **crime**, punishable
|
||||
with a sentence to read the entire Git documentation.
|
||||
|
||||
Manually ignoring the generated files would be quite tedious, thus
|
||||
Git has a mechanism to automatically ignore changes matching a user
|
||||
defined pattern.
|
||||
It is very simple, just add a file `.gitignore` to any directory in
|
||||
your repository.
|
||||
Such an ignore file is applied for the directory they reside in and
|
||||
all lower levels.
|
||||
An ignore file has no effect on its parent or sibling directories.
|
||||
|
||||
Here is an example of a `.gitignore`:
|
||||
|
||||
```git
|
||||
# ignore build directory (and all its contents)
|
||||
build/
|
||||
|
||||
# ignore all pdf
|
||||
*.pdf
|
||||
# do not ignore specific pdf
|
||||
!readme.pdf
|
||||
```
|
||||
|
||||
|
||||
## Branches
|
||||
|
||||
A branch is essentially a named reference to a list of commits,
|
||||
originating from a commit on the main branch.
|
||||
Here is an ASCII graphic to try and explain the concept.
|
||||
Keep in mind, that commits (represented by capital letters) contain
|
||||
only the differences to their parents.
|
||||
|
||||
```
|
||||
A -- B -- D ------ G (main)
|
||||
\
|
||||
C -- E -- F (branch)
|
||||
```
|
||||
|
||||
Branches are a good tool to work on a project with several
|
||||
contributors without solving conflicts on every commit.
|
||||
Or to quickly try an idea without the risk to poison the development
|
||||
branch.
|
||||
|
||||
Imagine the a scenario, where you work with a colleague on a project.
|
||||
Your colleague works one part and you on another but both of you have
|
||||
to make changes to the glue logic inbetween.
|
||||
The one who commits second will have to solve conflicts.
|
||||
This still applies when both of you work on separate branches, but
|
||||
only once, when you rebase or merge your branch back to mainline.
|
||||
While working on your branch you never need to solve conflicts.
|
||||
|
||||
Another use for branches is to develop several features concurrently.
|
||||
Working with branches you jump between the features without having to
|
||||
worry about one to interfere with another.
|
||||
Also you can have a branch reviewed while working on a different
|
||||
feature.
|
||||
|
||||
|
||||
### Creating/switching a branch
|
||||
|
||||
There are at least two methods to create a branch.
|
||||
Here are the two that come to mind first:
|
||||
|
||||
```
|
||||
# create a branch,
|
||||
# but do not switch to the created branch
|
||||
git branch <branch-name>
|
||||
|
||||
# create a branch and switch to it
|
||||
git checkout -b <branch-name>
|
||||
```
|
||||
|
||||
If your working tree is clean, you can switch between branches with
|
||||
the following commands:
|
||||
|
||||
```
|
||||
# change to branch (or commit)
|
||||
# (does not create branches or commits)
|
||||
git checkout <branch-name/commit-hash>
|
||||
|
||||
# change to branch
|
||||
git switch <branch-name>
|
||||
```
|
||||
|
||||
|
||||
## Merging/rebasing a branch
|
||||
|
||||
When a feature is implemented and tested, it is usually to be
|
||||
integrated into the main branch.
|
||||
|
||||
Git provides two ways to achieve this, merging and rebasing.
|
||||
|
||||
The following subchapter explains the two philosophies.
|
||||
|
||||
|
||||
### *Merge* or *rebase*?
|
||||
|
||||
> My quick answer is: Does not matter, but use only one strategy per
|
||||
> repository.
|
||||
|
||||
This chapter will give a quick explanation of what *merging* and
|
||||
*rebasing* means and at the end I explain my opinion.
|
||||
|
||||
|
||||
**Merging** means creating a commit with two parents.
|
||||
When merging, all conflicts are resolved in one merge commit.
|
||||
|
||||
Here is some ASCII art to visualise this concept:
|
||||
|
||||
```
|
||||
# merge
|
||||
|
||||
A -- C (main)
|
||||
\
|
||||
B -- D -- E (feature branch)
|
||||
|
||||
| | | |
|
||||
v v v v
|
||||
|
||||
A -- C ------ F (main)
|
||||
\ /
|
||||
B -- D -- E (feature branch)
|
||||
```
|
||||
|
||||
|
||||
**Rebasing** means to recalculate the deltas from a new origin.
|
||||
This way one can just add (fast forward) the commits of the feature
|
||||
branch on top of the main branch.
|
||||
When rebasing, conflicts are resolved in the commit of the feature
|
||||
branch, that introduces the conflict.
|
||||
|
||||
Here is some ASCII art to visualise this concept:
|
||||
|
||||
```
|
||||
# rebase
|
||||
|
||||
A -- C (main)
|
||||
\
|
||||
B -- D -- E (feature branch)
|
||||
|
||||
| | | |
|
||||
v v v v
|
||||
|
||||
A -- C (main)
|
||||
\
|
||||
B' -- D' -- E' (feature branch)
|
||||
|
||||
# rebased feature-branch on top of main
|
||||
|
||||
| | | |
|
||||
v v v v
|
||||
|
||||
A -- C -- B' -- D' -- E' (main)
|
||||
|
||||
# rebased main on top of rebased feature-branch
|
||||
# (no conflicts -> fast forward)
|
||||
```
|
||||
|
||||
|
||||
**Conclusion** both strategies have advantages and disadvantages:
|
||||
|
||||
* *Merging* has the advantage of keeping more information.
|
||||
* *Rebasing* has the advantage of better readability of the history.
|
||||
* Some actions for history cleanup require the interactive *rebase*
|
||||
tool, which may be a *rebasing* argument for some.
|
||||
|
||||
I personally have a preference for *rebasing* due to the cleaner
|
||||
history, but find it perfectly reasonable to use *merging*.
|
||||
|
||||
|
||||
### Merging
|
||||
|
||||
When merging, checkout the destination branch and merge the feature
|
||||
branch into it.
|
||||
You will get one merge commit, that solves all conflicts.
|
||||
Both branches stay in your history and are displayed side to side in
|
||||
the graph view.
|
||||
|
||||
Here I explain the procedure of a merge, below you find the commands
|
||||
used.
|
||||
|
||||
1) First synchronise the local with the remote repository.
|
||||
1) Checkout the **destination** branch.
|
||||
1) Merge the feature branch into your current (destination) branch.
|
||||
1) This may cause conflicts.
|
||||
1) Get a list of files containing conflicts with `git status`.
|
||||
1) Resolve conflicts (see [Resolving conflicts][conflicts])
|
||||
1) Continue with `git merge --contine`, choose a message for the
|
||||
merge commit, save and close.
|
||||
1) Synchronise the remote with `git push`.
|
||||
|
||||
|
||||
### Rebasing
|
||||
|
||||
When rebasing, checkout the feature branch and rebase it on the main
|
||||
branch.
|
||||
This way all conflicts are resolved on the feature branch and the
|
||||
commits can be fast forwarded to the main branch.
|
||||
Rebasing requires a force push.
|
||||
|
||||
Many projects prohibit force pushes on the main branch, so rebasing
|
||||
the main branch on top of the feature branch is not even an option.
|
||||
|
||||
> Be very careful with force pushes.
|
||||
>
|
||||
> Always substitue `--force` with `--force-with-lease`.
|
||||
> This at least disables one to overwrite commits on the remote,
|
||||
> that are not known locally.
|
||||
|
||||
Here I explain the procedure of a rebase, below you find the commands
|
||||
used.
|
||||
|
||||
1) First synchronise the local with the remote repository.
|
||||
1) Checkout the **feature** branch.
|
||||
1) Rebase the feature branch to the destination branch
|
||||
1) This might cause conflicts.
|
||||
1) Get a list of files containing conflicts with `git status`.
|
||||
1) Resolve conflicts (see [Resolving conflicts][conflicts]).
|
||||
1) Continue the rebase with `git rebase --continue`.
|
||||
1) Repeat until all conflicts are solved.
|
||||
When rebasing, conflicts are solved in the commit, which introduces
|
||||
them.
|
||||
Thus one may have to repeat these steps as many times, as there are
|
||||
commits to rebase.
|
||||
1) Force push your rebased branch (with `--force-with-lease`).
|
||||
1) Check out the destination branch.
|
||||
1) Rebase destination branch to feature-branch.
|
||||
1) Push rebased destination branch (this does not require force).
|
||||
|
||||
```sh
|
||||
# fetch the newest state from the remote
|
||||
git fetch --all
|
||||
|
||||
# switch branch
|
||||
git checkout <feature-branch>
|
||||
|
||||
# rebase current branch onto <branch>
|
||||
git rebase <branch>
|
||||
|
||||
# show files containing conflicts during a rebase
|
||||
git status
|
||||
|
||||
# stage solved conflicts
|
||||
git add <file/directory>
|
||||
|
||||
# continue rebase after conflicts are solved
|
||||
git rebase --continue
|
||||
|
||||
# push rebased commits to feature branch
|
||||
#
|
||||
# NEVER USE `--force`, SUBSTITUE WITH `--force-with-lease`!
|
||||
#
|
||||
# be very careful with force pushes `--force-with-lease` is
|
||||
# still a potential foot gun!
|
||||
git push --force-with-lease
|
||||
```
|
||||
|
||||
|
||||
## Resolving conflicts
|
||||
|
||||
For resolving conflicts you can either use a graphical mergetool, or
|
||||
decide to do it manually (in the file itself).
|
||||
I do not use any GUI for Git, so can not give you any
|
||||
recommendations, or instructions for how to use them.
|
||||
I will just describe the manual approach, it is no more difficult
|
||||
really.
|
||||
|
||||
Git will insert searchable sequences around the conflicts and label
|
||||
both versions with the source of the change.
|
||||
See the example below.
|
||||
|
||||
```
|
||||
<<<<<<< HEAD
|
||||
hello world
|
||||
=======
|
||||
blargh
|
||||
>>>>>>> f837762 (b)
|
||||
```
|
||||
|
||||
To solve a conflict, decide which parts you want to keep and delete
|
||||
the rest of the changes encased by Gits markers.
|
||||
If you want or need to you can also mix the changes of both commits.
|
||||
Then delete the markers and save the file.
|
||||
Stage the file and continue the merge or rebase with
|
||||
`git merge --continue` or `git rebase --continue` respectively.
|
||||
|
||||
|
||||
## History inspection
|
||||
|
||||
You can inspect the history with `git log`.
|
||||
|
||||
Use `-n <number>` or just `-<number>` to show only <number> entries.
|
||||
|
||||
Use `--all` to show commits newer than HEAD, other branches and
|
||||
remote references.
|
||||
|
||||
Use `--oneline` to get a compact view. Combine it with `--graph` to
|
||||
display the commit tree as ASCII art.
|
||||
|
||||
Use `git show <commit-hash/commit-reference>` to get the diff of the
|
||||
commit.
|
||||
|
||||
|
||||
## History rewriting
|
||||
|
||||
This is an advanced topic not recommended for beginners.
|
||||
I suggest to get used to work with Git first and come back once the
|
||||
desire to clean up the history rises.
|
||||
|
||||
The primary tool for history rewriting is the interactive rebase
|
||||
(`git rebase -i`).
|
||||
It provides a multitude of functions, reorder, reword and squash to
|
||||
name just a few.
|
||||
|
||||
Using `git rebase -i <commit-reference/commit-hash>` will open a list
|
||||
of all commits following the provided commit.
|
||||
In the development repository for CT for example I used the command
|
||||
`git rebase -i HEAD~3` to get the following file opened by Git.
|
||||
|
||||
*The '~3' means three commits before HEAD.*
|
||||
|
||||
```
|
||||
pick a958dff # continued ct2->lab 05
|
||||
pick 52c15fd # elaborated root readme for ct1
|
||||
pick 555cf90 # moved and extended `git-introduction.md`
|
||||
|
||||
# Rebase 4abb7c9..555cf90 onto 4abb7c9 (3 commands)
|
||||
#
|
||||
# Commands:
|
||||
# p, pick <commit> = use commit
|
||||
# r, reword <commit> = use commit, but edit the commit message
|
||||
# e, edit <commit> = use commit, but stop for amending
|
||||
# s, squash <commit> = use commit, but meld into previous
|
||||
# commit
|
||||
# f, fixup [-C | -c] <commit> = like "squash" but keep only the
|
||||
# previous commit's log message, unless -C
|
||||
# is used, in which case keep only this
|
||||
# commit's message; -c is same as -C but
|
||||
# opens the editor
|
||||
# x, exec <command> = run command (the rest of the line) using
|
||||
# shell
|
||||
# b, break = stop here (continue rebase later with 'git rebase
|
||||
# --continue')
|
||||
# d, drop <commit> = remove commit
|
||||
# l, label <label> = label current HEAD with a name
|
||||
# t, reset <label> = reset HEAD to a label
|
||||
# m, merge [-C <commit> | -c <commit>] <label> [# <oneline>]
|
||||
# create a merge commit using the original
|
||||
# merge commit's message (or the oneline, if
|
||||
# no original merge commit was specified);
|
||||
# use -c <commit> to reword the commit
|
||||
# message
|
||||
# u, update-ref <ref> = track a placeholder for the <ref> to
|
||||
# be updated to this position in the new
|
||||
# commits. The <ref> is updated at the end
|
||||
# of the rebase.
|
||||
#
|
||||
# These lines can be re-ordered; they are executed from top
|
||||
# to bottom.
|
||||
#
|
||||
# If you remove a line here THAT COMMIT WILL BE LOST.
|
||||
#
|
||||
# However, if you remove everything, the rebase will be
|
||||
# aborted.
|
||||
```
|
||||
|
||||
The commits are listed oldest to youngest from the top.
|
||||
I could reorder them by just moving the lines.
|
||||
Or remove a commit by changing the 'pick' at start of its line to
|
||||
'drop'.
|
||||
|
||||
I will not go into detail on the available actions, just one note on
|
||||
'squash' (combine), which is a function I use regularly.
|
||||
Commits are always squashed into their parents (upwards in this list).
|
||||
|
||||
After editing the list as intended, save and close the file.
|
||||
If you chose actions, which need further input, Git will
|
||||
open another file.
|
||||
If you for example chose to reword a commit, Git will open a file with
|
||||
the old commit message, which you can edit, save and close.
|
||||
|
||||
Many functions require a force push.
|
||||
**Again be very careful with force pushes**.
|
||||
|
||||
|
||||
<!-- TODO:
|
||||
## General rules
|
||||
|
||||
**Do**
|
||||
|
||||
* commit small, cohesive changes
|
||||
* commit regularly
|
||||
* create a new, well named branch for every feature
|
||||
* merge branches promply (do not let them sit for too long)
|
||||
* add a `.gitignore` with rules sensible for the project
|
||||
|
||||
**Do not**
|
||||
|
||||
* commit files generated from the repositories sources, files
|
||||
generated elsewhere, which do not change, may be fine
|
||||
* force push unless it is your feature branch (there are **rare**
|
||||
exceptions for this rule)
|
||||
*
|
||||
-->
|
||||
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### I lost a commit!
|
||||
|
||||
Do not worry, use `git reflog`.
|
||||
The reference log keeps track of references and usually remembers
|
||||
"dangling" commits.
|
||||
This allows you to checkout or cherry-pick a "lost" commit or
|
||||
reference.
|
||||
|
||||
|
||||
### I tried to pull, but got a merge conflict?!
|
||||
|
||||
That is why you should always fetch first and pull only, after
|
||||
checking for conflicts.
|
||||
|
||||
This problem can occur, when someone rewrote the history and your
|
||||
local HEAD points to a commit that does no longer exist.
|
||||
|
||||
The solution is very easy:
|
||||
`git reset --hard <remote-name>/<branch-or-reference-name>`
|
||||
|
||||
If you have local commits that conflict with commits on the remote,
|
||||
see [Merging](#merging) or [Rebasing](#rebasing).
|
||||
|
||||
|
||||
## Further reading
|
||||
|
||||
Here a few functions this guide does not cover, for you to read up
|
||||
on, if interested:
|
||||
|
||||
* `git stash` allows to stash local changes, enabling actions like
|
||||
pull or rebase.
|
||||
* `git blame` can determine, who is responsible for code changes
|
||||
(line by line).
|
||||
* `git cherry-pick` allows to add single (or several) commits from a
|
||||
feature branch to the current branch, without having to add the
|
||||
entire feature branch.
|
||||
* `git bisect` uses binary search to determine the commit, which
|
||||
introduced a bug.
|
||||
* **command aliases** let you access often used command (with flags)
|
||||
via `git <alias>`.
|
||||
(This is distinct from the shells aliases.)
|
||||
|
||||
|
||||
## Glossary
|
||||
|
||||
+-------------------+-----------------------------------------------+
|
||||
| **Term** | **Description** |
|
||||
+:==================+:==============================================+
|
||||
| branch | Separate named reference originating from an |
|
||||
| | older commit on the source branch. |
|
||||
| | A branch can originate from main/master |
|
||||
| | (the trunk in the tree analogy) or any other |
|
||||
| | branch. |
|
||||
+-------------------+-----------------------------------------------+
|
||||
| commit | Repository state defined as delta to its |
|
||||
| | parent. |
|
||||
| | Each commit is identified by its commit hash, |
|
||||
| | a 40 byte long string of alphanumeric |
|
||||
| | characters. |
|
||||
| | The hash can be used in many Git commands, |
|
||||
| | e.g. `diff`, `reset` or `checkout`. |
|
||||
| | A commit usually has one parent, but can have |
|
||||
| | an arbitrary number of children, one for each |
|
||||
| | branch originating from the commit. |
|
||||
+-------------------+-----------------------------------------------+
|
||||
| commit reference | Named pointer to a specific commit. |
|
||||
| | An example would be `HEAD`, which points to |
|
||||
| | the currently checked out commit. |
|
||||
| | Branches and tags are references too. |
|
||||
+-------------------+-----------------------------------------------+
|
||||
| head | Pointer to commit currently checked out. |
|
||||
| | On remote it will usually point to *main*. |
|
||||
| | With `git checkout` one can checkout a |
|
||||
| | to e.g. test something or make new branch. |
|
||||
| | In such a case the head would point to that |
|
||||
| | commit. |
|
||||
+-------------------+-----------------------------------------------+
|
||||
| index / | `git add` puts file/directories (rather the |
|
||||
| staging area | changes made to them) into a cache, called |
|
||||
| | *index* or *staging area* (in arguments it is |
|
||||
| | also called chache). |
|
||||
| | `git commit` adds the changes in that cache |
|
||||
| | to the history with a hash, a descriptoin and |
|
||||
| | a few more information about the commit. |
|
||||
+-------------------+-----------------------------------------------+
|
||||
| working tree | Local copy of the repository. |
|
||||
| | a working tree is clean if it has no |
|
||||
| | uncommitted changes. |
|
||||
+-------------------+-----------------------------------------------+
|
||||
|
||||
|
||||
<!-- links -->
|
||||
[conflicts]: #resolving-conflicts
|
||||
[progit]: https://git-scm.com/book/en/v2
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 58 KiB |
@@ -5,6 +5,7 @@ This repository holds information I wrote down for quick access.
|
||||
|
||||
# Interesting topics to read up on
|
||||
|
||||
* [RSS feeds][ls-rss-feeds] & [newsraft][newsraft]
|
||||
* [LaTeX package *tikz*][tikz]
|
||||
* [HSV/HSL and colourspaces in general][hsl]
|
||||
* [GCCs handling of large immediate values][gcc-literals]
|
||||
@@ -12,6 +13,8 @@ This repository holds information I wrote down for quick access.
|
||||
|
||||
|
||||
<!-- links -->
|
||||
[ls-rss-feeds]: https://www.youtube.com/watch?v=hMH9w6pyzvU&list=PL-p5XmQHB_JRRnoQyjOfioJdDmu87DIJc&index=4
|
||||
[newsraft]: https://codeberg.org/newsraft/newsraft/releases
|
||||
[tikz]: https://nathantypanski.com/blog/2014-10-29-tikz-timing.html
|
||||
[hsl]: https://en.wikipedia.org/wiki/HSL_and_HSV#Use_in_end-user_software
|
||||
[gcc-literals]: https://medium.com/@python-javascript-php-html-css/understanding-gccs-handling-of-large-immediate-values-in-armv7-assembly-d8a906231b44
|
||||
|
||||
Reference in New Issue
Block a user