Compare commits
11 Commits
035ffe0de1
..
main
| Author | SHA1 | Date | |
|---|---|---|---|
| b7b627d1fe | |||
| 068a83b183 | |||
| a4848b9972 | |||
| dfce75c068 | |||
| 7b909ae4da | |||
| 62360da2e5 | |||
| f17b9ef0f6 | |||
| e78c74ea31 | |||
| 719a4f55d0 | |||
| eee25bf37c | |||
| 472289a641 |
+10
-138
@@ -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** |
|
||||
|----------:|----------:|:----------|:------------------------------|
|
||||
@@ -131,141 +137,7 @@ Ascii table because websites are unusable these days
|
||||
| 121 | `0x79` | y | |
|
||||
| 122 | `0x7A` | z | |
|
||||
| 123 | `0x7B` | { | left curly bracket |
|
||||
| 124 | `0x7C` | | | vertical bar |
|
||||
| 124 | `0x7C` | \| | vertical bar |
|
||||
| 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 |
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
# C operator precedence
|
||||
|
||||
+---------------+---------------+---------------------------------------+-------------------+
|
||||
| **piority** | **operator** | **description** | **associativity** |
|
||||
+==============:+:==============+:======================================+:==================+
|
||||
| 1 | `++`, `--` | *postfix*/suffix increment and | left to right |
|
||||
| | | decrement | |
|
||||
| +---------------+---------------------------------------+ |
|
||||
| | `()` | function call | |
|
||||
| +---------------+---------------------------------------+ |
|
||||
| | `[]` | array indexing/subscripting | |
|
||||
| +---------------+---------------------------------------+ |
|
||||
| | `.` | member access (struct or union) | |
|
||||
| +---------------+---------------------------------------+ |
|
||||
| | `->` | dereferencing member access | |
|
||||
| | | (struct or union) | |
|
||||
| +---------------+---------------------------------------+ |
|
||||
| | `(type){list}`| dereferencing member access | |
|
||||
| | | (struct or union) | |
|
||||
+---------------+---------------+---------------------------------------+-------------------+
|
||||
| 2 | `++`, `--` | *prefix* increment and decrement | right to left |
|
||||
| +---------------+---------------------------------------+ |
|
||||
| | `+`, `-` | unary plus and minus (sign) | |
|
||||
| +---------------+---------------------------------------+ |
|
||||
| | `!`, `~` | logical and bitwise `NOT` | |
|
||||
| +---------------+---------------------------------------+ |
|
||||
| | `(type)` | type cast | |
|
||||
| +---------------+---------------------------------------+ |
|
||||
| | `*` | dereferencing (indirection) | |
|
||||
| +---------------+---------------------------------------+ |
|
||||
| | `&` | referencing (get address of) | |
|
||||
| +---------------+---------------------------------------+ |
|
||||
| | `sizeof` | size of (builtin) | |
|
||||
| +---------------+---------------------------------------+ |
|
||||
| | `_Alignof`, | alignment requirement (C11 & C23 | |
|
||||
| | `alignof` | respectively) | |
|
||||
+---------------+---------------+---------------------------------------+-------------------+
|
||||
| 3 | `*`, `/`, `%` | multiplication, division and modulo | left to right |
|
||||
+---------------+---------------+---------------------------------------+-------------------+
|
||||
| 4 | `+`, `-` | addition and subtractionion | left to right |
|
||||
+---------------+---------------+---------------------------------------+-------------------+
|
||||
| 5 | `<<`, `>>` | bitwise left and right shift | left to right |
|
||||
+---------------+---------------+---------------------------------------+-------------------+
|
||||
| 6 | `<`, `<=`, | less than, less or equal, | left to right |
|
||||
| | `>`, `>=` | greater than and greater or euqal | |
|
||||
+---------------+---------------+---------------------------------------+-------------------+
|
||||
| 7 | `==`, `!=` | equals and unequals | left to right |
|
||||
+---------------+---------------+---------------------------------------+-------------------+
|
||||
| 8 | `&` | bitwise `AND` | left to right |
|
||||
+---------------+---------------+---------------------------------------+-------------------+
|
||||
| 9 | `^` | bitwise `XOR` (exclusive or) | left to right |
|
||||
+---------------+---------------+---------------------------------------+-------------------+
|
||||
| 10 | `|` | bitwise `OR` (inclusive or) | left to right |
|
||||
+---------------+---------------+---------------------------------------+-------------------+
|
||||
| 11 | `&&` | logical `AND` | left to right |
|
||||
+---------------+---------------+---------------------------------------+-------------------+
|
||||
| 12 | `||` | bitwise `OR` | left to right |
|
||||
+---------------+---------------+---------------------------------------+-------------------+
|
||||
| 13 | `?:` | ternary conditional (inline if) | right to left |
|
||||
+---------------+---------------+---------------------------------------+-------------------+
|
||||
| 14 | `=` | simple assignment | right to left |
|
||||
| +---------------+---------------------------------------+ |
|
||||
| | `+=`, `-=` | assignment by sum and difference | |
|
||||
| +---------------+---------------------------------------+ |
|
||||
| | `*=`, `/=`, | simple assignment product, quotient | |
|
||||
| | `%=` | and remainder | |
|
||||
| +---------------+---------------------------------------+ |
|
||||
| | `<<=`, `>>=` | assignment by bitwise left or right | |
|
||||
| | | shift | |
|
||||
| +---------------+---------------------------------------+ |
|
||||
| | `&=`, `^=`, | assignment by bitwise `AND`, `XOR` | |
|
||||
| | `|=` | and `OR` | |
|
||||
+---------------+---------------+---------------------------------------+-------------------+
|
||||
| 15 | `,` | comma to separate entries in a list | left to right |
|
||||
+---------------+---------------+---------------------------------------+-------------------+
|
||||
Executable
+300
@@ -0,0 +1,300 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
### TODO: ensure files deleted in the maintainer repository are
|
||||
### also deleted in the students repository
|
||||
|
||||
### WARN: this script will not work unless the remote name is `origin` (default).
|
||||
|
||||
### WARN: this script expects you to connect to github via ssh.
|
||||
### ensure you registered your public key.
|
||||
|
||||
# constant definitions
|
||||
|
||||
# WARN: make sure you understand the implications before
|
||||
# you change the value (or name) of a constant!
|
||||
|
||||
required_tools=(
|
||||
"cat"
|
||||
"dirname"
|
||||
"find"
|
||||
"git"
|
||||
"grep"
|
||||
"pandoc"
|
||||
"realpath"
|
||||
"sed"
|
||||
"tar"
|
||||
"tput"
|
||||
)
|
||||
common_dir="../common"
|
||||
laboratory_dir="./laboratories"
|
||||
student_repo_name="student-repository"
|
||||
student_repo_url="git@github.zhaw.ch:CT/ct1-students.git"
|
||||
code_start="STUDENTS: To be programmed"
|
||||
code_end="END: To be programmed"
|
||||
make_start="solution[s]*=start"
|
||||
make_end="solution[s]*=end"
|
||||
md_solution_start="solution[s]*=start"
|
||||
md_solution_end="solution[s]*=end"
|
||||
md_student_start="student[s]*=start"
|
||||
md_student_end="student[s]*=end"
|
||||
keili_dir_name="keil"
|
||||
archive_name="release.tar"
|
||||
exclude_file_name=".release-ignore"
|
||||
|
||||
# sanity checks for variables
|
||||
if [[ "${laboratory_dir}" =~ ".." ]]; then
|
||||
echo "'laboratory_dir' has to be a child directory of the one containing this script"
|
||||
fi
|
||||
if [[ "." != "$(dirname "${student_repo_name}")" ]]; then
|
||||
echo "'student_repo_name' may not contain directories!"
|
||||
exit 0
|
||||
fi
|
||||
if [[ "." != "$(dirname "${keili_dir_name}")" ]]; then
|
||||
echo "'keili_dir_name' may not contain directories!"
|
||||
exit 0
|
||||
fi
|
||||
if [[ "." != "$(dirname "${exclude_file_name}")" ]]; then
|
||||
echo "'exclude_file_name' may not contain directories!"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# helper function declarations
|
||||
|
||||
## print highlighted text
|
||||
##
|
||||
## used the same as `echo`
|
||||
function print_highlighted {
|
||||
if ! $(which tput &>/dev/null) || [[ -z "$(tput smso)" ]]; then
|
||||
echo "$*"
|
||||
return 0
|
||||
fi
|
||||
|
||||
tput smso
|
||||
echo "$*"
|
||||
tput sgr0
|
||||
}
|
||||
|
||||
## print yellow text
|
||||
##
|
||||
## used the same as `echo`
|
||||
function print_warning {
|
||||
if ! $(which tput &>/dev/null); then
|
||||
echo "$*"
|
||||
return 0
|
||||
fi
|
||||
|
||||
tput setaf 3
|
||||
echo "$*"
|
||||
tput sgr0
|
||||
}
|
||||
|
||||
## print red text
|
||||
##
|
||||
## used the same as `echo`
|
||||
function print_error {
|
||||
if ! $(which tput &>/dev/null); then
|
||||
echo "$*"
|
||||
return 0
|
||||
fi
|
||||
|
||||
tput setaf 1
|
||||
echo "$*"
|
||||
tput sgr0
|
||||
}
|
||||
|
||||
# main logic
|
||||
|
||||
# ensure the required tools are available
|
||||
unset error_message
|
||||
for tool in "${required_tools}"; do
|
||||
if ! $(which "${tool}" &>/dev/null); then
|
||||
error_message+="${tool}"
|
||||
fi
|
||||
done
|
||||
if [[ -n "${error_message}" ]]; then
|
||||
print_error "missing the following tools: [ ${error_message} ]"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# ensure commands are executed in the directory where the
|
||||
# script is located
|
||||
root_dir="$(realpath "${BASH_SOURCE}" | dirname -)"
|
||||
cd "${root_dir}"
|
||||
|
||||
# check that there are no paths with spaces
|
||||
illegal_paths="$(find . -type d -name ".git" -prune -o -name "*" -print |
|
||||
sort | grep ' ')"
|
||||
if [[ -n "${illegal_paths}" ]]; then
|
||||
print_error "no spaces in paths allowed!"
|
||||
print_error "the following paths are illegal:"
|
||||
echo ""
|
||||
echo "${illegal_paths}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# ensure the working tree of the maintainer repository is not behind
|
||||
# no need to check the students repository, as it is derived from the
|
||||
# maintainer repository
|
||||
git fetch &>/dev/null
|
||||
if [[ -n "$(git diff origin/HEAD)" ]]; then
|
||||
print_warning "working tree of the maintainer repository differs from the remotes head."
|
||||
print_warning "pull and/or commit/push first to resolve the differences."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# remove trailing whitespace and convert to unix file format
|
||||
bash "${common_dir}/trailing-whitespace.sh" -u .
|
||||
|
||||
# ensure the students repository is checked out
|
||||
if [[ ! -d "${student_repo_name}" ]]; then
|
||||
print_highlighted "cloning students repository"
|
||||
git clone "${student_repo_url}" "${student_repo_name}"
|
||||
fi
|
||||
|
||||
# ensure the students repository is ignored
|
||||
if [[ -z "$(cat "./.gitignore" | grep "${student_repo_name}")" ]]; then
|
||||
echo "${student_repo_name}/" >>"./.gitignore"
|
||||
fi
|
||||
|
||||
# remove solutions from source code
|
||||
code_files=($(
|
||||
find "${laboratory_dir}" \
|
||||
-type f \
|
||||
-name "*.[chs]"
|
||||
))
|
||||
|
||||
for file in "${code_files[@]}"; do
|
||||
sed -i "
|
||||
/${code_start}/,/${code_end}/ {
|
||||
/${code_start}/n
|
||||
/${code_end}/!d
|
||||
}" ${file}
|
||||
|
||||
# add blank lines to show where code goes
|
||||
sed -i "/${code_start}/a\\\\" ${file}
|
||||
sed -i "/${code_start}/a\\\\" ${file}
|
||||
sed -i "/${code_start}/a\\\\" ${file}
|
||||
done
|
||||
|
||||
echo "> removed solutions from source files."
|
||||
|
||||
# removing solutions from makefiles
|
||||
make_files=($(
|
||||
find "${laboratory_dir}" \
|
||||
-type f \
|
||||
-name "Makefile" \
|
||||
-or \
|
||||
-name "*.mk"
|
||||
))
|
||||
|
||||
for file in "${make_files[@]}"; do
|
||||
sed -i "/${make_start}/,/${make_end}/d" ${file}
|
||||
done
|
||||
|
||||
# remove solutions from lab instructions
|
||||
md_files=($(
|
||||
find "${laboratory_dir}" \
|
||||
-type f \
|
||||
-name "*.md"
|
||||
))
|
||||
|
||||
for file in "${md_files[@]}"; do
|
||||
sed -i "/${md_solution_start}/,/${md_solution_end}/d" ${file}
|
||||
sed -i "/${md_student_start}/d" ${file}
|
||||
sed -i "/${md_student_end}/d" ${file}
|
||||
done
|
||||
|
||||
echo "> removed solutions from lab instructions."
|
||||
|
||||
# convert readmes from `pandoc markdown` to `github flavoured markdown` and pdf
|
||||
echo "converting markdown files to pdfs"
|
||||
echo "(this may take a while)"
|
||||
|
||||
template="$(realpath "${common_dir}/template.tex")"
|
||||
unset pdf_files
|
||||
for file in "${md_files[@]}"; do
|
||||
filename="${file##*/}"
|
||||
pushd "${file%/*}" &>/dev/null
|
||||
pandoc \
|
||||
-f markdown \
|
||||
-t pdf \
|
||||
--pdf-engine pdflatex \
|
||||
--listings \
|
||||
--template "${template}" \
|
||||
"${filename}" \
|
||||
-o "${filename/%md/pdf}"
|
||||
pandoc \
|
||||
-f markdown \
|
||||
-t gfm \
|
||||
"${filename}" \
|
||||
-o "${filename}"
|
||||
popd &>/dev/null
|
||||
pdf_files+=("${file/%md/pdf}")
|
||||
done
|
||||
unset template
|
||||
|
||||
echo "> converted readme files to github flavoured markdown."
|
||||
|
||||
# generate zip archives of keili projects
|
||||
keili_dirs=($(find . -type d -name "${keili_dir_name}"))
|
||||
for item in "${keili_dirs[@]}"; do
|
||||
pushd "$(dirname "${item}")" &>/dev/null
|
||||
zip -r "${keili_dir_name}.zip" "${keili_dir_name}" &>/dev/null
|
||||
popd &>/dev/null
|
||||
done
|
||||
unset keili_dirs
|
||||
|
||||
keili_archives=($(find "${laboratory_dir}" -name "${keili_dir_name}.zip"))
|
||||
|
||||
# copy modified contents to students repository
|
||||
exclude_patterns=("${exclude_file_name}")
|
||||
exclude_patterns+=("${keili_dir_name}")
|
||||
exclude_patterns+=("*.pptx")
|
||||
exclude_patterns+=("*.docx")
|
||||
|
||||
# collect exclude globs
|
||||
ignore_files=($(find . -type f -iname "${exclude_file_name}"))
|
||||
for file in "${ignore_files[@]}"; do
|
||||
temp_path="$(dirname ${file})/"
|
||||
temp_patterns=($(cat "${file}"))
|
||||
exclude_patterns+=(${temp_patterns[@]/#/${temp_path}})
|
||||
done
|
||||
|
||||
# remove contents of the student repository to avoid
|
||||
# orphaned files/directories
|
||||
find "${student_repo_name}" \
|
||||
-mindepth 1 \
|
||||
-maxdepth 1 \
|
||||
-not -name ".git" \
|
||||
-exec rm -rf {} \;
|
||||
|
||||
# create release using `tar`
|
||||
tar -cf "${archive_name}" \
|
||||
-h \
|
||||
--exclude-vcs \
|
||||
--exclude-vcs-ignore \
|
||||
--exclude="${archive_name}" \
|
||||
"${exclude_patterns[@]/#/--exclude=}" \
|
||||
"${keili_archives[@]/#/--add-file=}" \
|
||||
"${pdf_files[@]/#/--add-file=}" \
|
||||
.
|
||||
tar -xf "${archive_name}" \
|
||||
-C "${student_repo_name}/"
|
||||
|
||||
# reset repository after release creation
|
||||
git reset --hard &>/dev/null
|
||||
git clean -fd &>/dev/null
|
||||
rm "${keili_archives[@]}" "${pdf_files[@]}"
|
||||
|
||||
# print message to report success and a reminder to commit and
|
||||
# push the students repository
|
||||
relative_path="$(dirname "${BASH_SOURCE}")/${student_repo_name}"
|
||||
|
||||
echo ""
|
||||
echo "successfully prepared the release for the students repository."
|
||||
echo "generated release is found at \`${relative_path}\`."
|
||||
echo ""
|
||||
|
||||
print_highlighted "remember to commit and push the generated release!"
|
||||
|
||||
echo ""
|
||||
@@ -0,0 +1,18 @@
|
||||
|
||||
SHELL := /usr/bin/env bash
|
||||
|
||||
SRC_DIR := ./src
|
||||
INC_DIR := ./inc
|
||||
OBJ_DIR := ./obj
|
||||
BIN_DIR := ./bin
|
||||
LIB_DIR := ../../libctboard
|
||||
COMMON_DIR := ../../common
|
||||
|
||||
AS_SRC := table.s
|
||||
|
||||
C_DEF := PLATFORM_M0
|
||||
C_INC :=
|
||||
C_SRC :=
|
||||
|
||||
include $(COMMON_DIR)/root.mk
|
||||
include $(COMMON_DIR)/pdf.mk
|
||||
@@ -0,0 +1,40 @@
|
||||
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 $(COMMON_DIR)/template.tex \
|
||||
-f markdown \
|
||||
-t pdf \
|
||||
$(VERBOSITY) \
|
||||
-o $@ \
|
||||
$<
|
||||
|
||||
@@ -0,0 +1,187 @@
|
||||
|
||||
SHELL := /usr/bin/env bash
|
||||
|
||||
PREFIX := arm-none-eabi-
|
||||
CC := $(PREFIX)gcc
|
||||
COPY := $(PREFIX)objcopy
|
||||
SIZE := $(PREFIX)size
|
||||
GDB := $(PREFIX)gdb
|
||||
|
||||
OCD := openocd
|
||||
|
||||
NAME := application
|
||||
|
||||
OPT_LEVEL_CC := -g \
|
||||
-O0
|
||||
|
||||
TARGET_FLAGS := -mcpu=cortex-m4 \
|
||||
-mthumb \
|
||||
-mfpu=fpv4-sp-d16 \
|
||||
-mfloat-abi=hard
|
||||
|
||||
WG := -Wall \
|
||||
-Wextra \
|
||||
-Wpedantic \
|
||||
-Werror
|
||||
|
||||
WCC := -Wconversion \
|
||||
-Wsign-conversion \
|
||||
-Wsign-compare \
|
||||
-Wcast-align=strict \
|
||||
-Wfloat-equal \
|
||||
-Wlogical-op
|
||||
|
||||
AS_FLAGS := $(TARGET_FLAGS) \
|
||||
$(OPT_LEVEL_CC) \
|
||||
$(VERB_LEVEL) \
|
||||
$(WG) \
|
||||
-Wa,-a,-ad,-alms=$(BIN_DIR)/$(NAME).lst \
|
||||
-x assembler-with-cpp
|
||||
|
||||
C_DEF := $(addprefix -D, $(C_DEF))
|
||||
C_INC := $(addprefix -I, $(C_INC))
|
||||
C_FLAGS := $(TARGET_FLAGS) \
|
||||
$(OPT_LEVEL_CC) \
|
||||
$(VERB_LEVEL) \
|
||||
$(WG) \
|
||||
$(WCC) \
|
||||
-Wa,-a,-ad,-alms=$(BIN_DIR)/$(NAME).lst \
|
||||
$(C_DEF) \
|
||||
$(C_INC)
|
||||
|
||||
FLAGS_FILE := ./compile_flags.txt
|
||||
|
||||
LST_DIR := $(BIN_DIR)/list-files
|
||||
|
||||
LIBCTBOARD := $(LIB_DIR)/lib/libctboard.a
|
||||
LIB_PATHS += $(LIB_DIR)/lib
|
||||
LIB_NAMES += ctboard
|
||||
|
||||
LINKER_FLAGS := $(TARGET_FLAGS) \
|
||||
-static \
|
||||
-nostartfiles \
|
||||
$(addprefix -L, $(LIB_PATHS)) \
|
||||
-lm \
|
||||
-lnosys \
|
||||
-Wl,--start-group \
|
||||
$(addprefix -l, $(LIB_NAMES)) \
|
||||
-Wl,--end-group \
|
||||
-specs=nosys.specs \
|
||||
-specs=nano.specs \
|
||||
-Wl,-Map,$(BIN_DIR)/$(NAME).map \
|
||||
-Wl,-e,Reset_Handler \
|
||||
-Wl,--gc-sections
|
||||
|
||||
LD_SCRIPT := $(LIB_DIR)/lib/linker-script.ld
|
||||
GDB_INIT := $(COMMON_DIR)/.gdbinit
|
||||
OCD_CONFIG := $(COMMON_DIR)/openocd.cfg
|
||||
|
||||
OBJ := $(addprefix $(OBJ_DIR)/, $(AS_SRC:.s=.o)) \
|
||||
$(addprefix $(OBJ_DIR)/, $(C_SRC:.c=.o))
|
||||
|
||||
ELF := $(BIN_DIR)/$(NAME).elf
|
||||
BIN := $(basename $(ELF)).bin
|
||||
|
||||
MKDIR := $(OBJ_DIR) \
|
||||
$(BIN_DIR) \
|
||||
$(LST_DIR)
|
||||
|
||||
VPATH := $(SRC_DIR)
|
||||
|
||||
|
||||
.PHONY: all clean clean_all dbgsrv flash launchgdb rebuild test
|
||||
|
||||
|
||||
all: $(LIBCTBOARD) $(MKDIR) $(BIN) $(FLAGS_FILE)
|
||||
|
||||
|
||||
flash: $(MKDIR) $(BIN)
|
||||
-$(OCD) -f $(OCD_CONFIG) \
|
||||
-c "program $(BIN) verify exit 0x08000000"
|
||||
|
||||
|
||||
dbgsrv: flash
|
||||
-$(OCD) -f $(OCD_CONFIG) \
|
||||
-c "gdb_port 4500" \
|
||||
-c "init; reset run;"
|
||||
|
||||
|
||||
launchgdb: $(ELF) $(BIN) $(GDB_INIT)
|
||||
$(GDB) --command=$(GDB_INIT) $<
|
||||
|
||||
|
||||
$(MKDIR):
|
||||
mkdir -p $@
|
||||
|
||||
|
||||
#
|
||||
# The sections have to correspond with the
|
||||
# sections defined in the linker script who
|
||||
# are directed to be located in the flash
|
||||
# memory area.
|
||||
#
|
||||
$(BIN): $(ELF)
|
||||
$(COPY) --output-target=binary \
|
||||
-j .isr_vector \
|
||||
-j .stack \
|
||||
-j .heap \
|
||||
-j .text \
|
||||
-j .my_code \
|
||||
-j .my_const \
|
||||
-j .my_var \
|
||||
-j .rodata\
|
||||
-j .ARM.extab \
|
||||
-j .ARM \
|
||||
-j .preinit_array \
|
||||
-j .init_array \
|
||||
-j .fini_array \
|
||||
-j .data \
|
||||
-j .ccmram \
|
||||
-j .ARM.extab \
|
||||
-j .ARM \
|
||||
$< $@
|
||||
chmod -x $@
|
||||
@printf "\n"
|
||||
|
||||
|
||||
$(ELF): $(OBJ)
|
||||
$(CC) -o $@ $^ $(LINKER_FLAGS) -T $(LD_SCRIPT)
|
||||
chmod -x $@
|
||||
|
||||
|
||||
$(OBJ_DIR)/%.o: %.s
|
||||
$(CC) \
|
||||
$(AS_FLAGS) \
|
||||
-Wa,-a,-ad,-alms=$(LST_DIR)/$*.lst \
|
||||
-c $< \
|
||||
-o $@
|
||||
|
||||
|
||||
$(OBJ_DIR)/%.o: %.c
|
||||
$(CC) \
|
||||
$(C_FLAGS) \
|
||||
-Wa,-a,-ad,-alms=$(LST_DIR)/$*.lst \
|
||||
-c $< \
|
||||
-o $@
|
||||
|
||||
|
||||
$(LIBCTBOARD):
|
||||
echo "$(LIB_DIR)"
|
||||
make -C "$(LIB_DIR)" rebuild
|
||||
|
||||
|
||||
# this is to satisfy clangd (lsp client)
|
||||
$(FLAGS_FILE):
|
||||
@echo "$(C_FLAGS)" | sed 's/ /\n/g' > $@
|
||||
|
||||
|
||||
clean:
|
||||
-rm -rf $(MKDIR) $(FLAGS_FILE)
|
||||
|
||||
|
||||
clean_all:: clean
|
||||
|
||||
|
||||
rebuild: clean all
|
||||
|
||||
|
||||
@@ -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 |
@@ -1,3 +1,3 @@
|
||||
# bits and bops
|
||||
|
||||
> remember xorg config screentearing option
|
||||
> remember xorg config screentearing option (obsolete with xlibre)
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
# zegonix' documentation
|
||||
|
||||
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]
|
||||
* [How do WAV files work][wav-files]
|
||||
|
||||
|
||||
<!-- 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
|
||||
[wav-files]: https://stackoverflow.com/questions/16075233/reading-and-processing-wav-file-data-in-c-c
|
||||
Reference in New Issue
Block a user