Skip to content

Commit e3aea31

Browse files
committed
content: improved bash scripting, minor improvements to advanced git and workflows
1 parent 8963b44 commit e3aea31

File tree

4 files changed

+219
-39
lines changed

4 files changed

+219
-39
lines changed

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,7 @@ A short course about learning to use bash and git as a software developer.
66

77
All content compiled and prepared by [Mihail Mikov](https://github.com/debel) with linked attributions within the text.
88

9+
All materials linked from primary sources, mainly: the [git docs](https://git-scm.com/docs), and the [Pro git book](https://git-scm.com/book)
10+
911
The theme is a port of the [Hugo Terminal Theme](https://github.com/panr/hugo-theme-terminal) created by [panr](https://github.com/panr). All design decisions, colour schemes, and visual aesthetics are credited to the original author. Astro port created by [Dennis Klappe](https://github.com/dennisklappe).
1012

src/content/lessons/advanced-git-features.md

Lines changed: 22 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,8 @@ There are many ways to get to a commit.
2323
```bash
2424
master^ # E (parent commit)
2525
master~3 # A (third ancestor)
26-
C^^ # A
27-
B~1 # A
26+
C^^ # A (parent of parent)
27+
B~1 # A (parent)
2828
^B # everything except A and B
2929
```
3030

@@ -33,12 +33,12 @@ B~1 # A
3333
*parents* vs *ancestors*
3434
![history with merge](https://git-scm.com/book/en/v2/images/basic-merging-2.png)
3535
```bash
36-
master^ # C4 first parent of a merge commit
37-
master^2 # C5 second parent of a merge commit
36+
master^ # C4 -- first parent of a merge commit
37+
master^2 # C5 -- second parent of a merge commit
3838

39-
iss53~2 # C2 second ancestor i.e. the parent of the parent
39+
iss53~2 # C2 -- second ancestor (the parent of the parent)
4040

41-
master^2~1 # C3
41+
master^2~1 # C3 -- the parent of the second parent
4242
```
4343

4444
---
@@ -77,7 +77,7 @@ HEAD@{5.days.ago}
7777

7878
## Blame
7979

80-
`blame` allow us to understand when changes were made.
80+
`blame` allow us to understand who and when made changes.
8181

8282
```bash
8383
# display which commit last changed each line of my-file
@@ -139,7 +139,7 @@ The main difference between a Lightweight tag and a branch is that tags
139139
**CANNOT** be changed to point to a different commit.
140140

141141
```bash
142-
# tag the current commit as v1
142+
# tag the current commit as v2
143143
git tag v2.0.0
144144

145145
# tag a previous commit in the history
@@ -160,7 +160,7 @@ They can be signed (like commits). They **CANNOT** be moved as well.
160160
git tag -a v2.3.0 -m "Release v2.3: Blue Kiwi"
161161

162162
# create a signed annotated tag
163-
git tag -a -s v2.5.0 -m "Notes fro version 2.5
163+
git tag -a -s v2.5.0 -m "Notes for version 2.5"
164164
```
165165

166166
---
@@ -213,7 +213,8 @@ git bisect bad
213213
# mark a commit as good i.e. not containing the bug
214214
git bisect good 25aef7
215215

216-
# delete the bisect state and return to the initial starting commit
216+
# delete the bisect state and return
217+
# to the initial starting commit
217218
git bisect reset
218219
```
219220

@@ -222,19 +223,21 @@ git bisect reset
222223
Bisect will try to choose the minimum number of commits you need to review.
223224

224225
You can use an appropriate command to automatically validate if the commit is good or bad.
225-
(e.g. compile the code, run tests, or performance benchmarks)
226+
(e.g. compile the code, run tests or performance benchmarks)
226227

227228
---
228229

229230
## Multiple work-trees
230231

231232
Git allows you to have multiple versions checked-out at the same time:
232233
```bash
233-
# creates a branch called bugfix and checks out into a working directory
234-
# called bugfix in the parent of the current directory
234+
# creates a branch called bugfix and checks it out
235+
# into a working directory called bugfix
236+
# in the parent of the current directory
235237
git workspace add ../bugfix
236238

237-
# checkout branch origin/broken into a independent working directory
239+
# checkout branch origin/broken into a
240+
# separate working directory in your home directory
238241
git worktree add ~/my-project-bugfix origin/broken
239242
```
240243

@@ -245,7 +248,8 @@ git worktree add ~/my-project-bugfix origin/broken
245248
git worktree list
246249

247250
# delete a worktree, needs to be clean
248-
# the corresponding branch is still part of the project history
251+
# the corresponding branch is still
252+
# part of the project history
249253
git worktree remove bugfix
250254
```
251255

@@ -277,7 +281,7 @@ but all files will be untracked.
277281
### Use case: deploy branch
278282

279283
After creating a disconnected (orphan) branch, you can
280-
delete or ignore all "regular" project files, leaving
284+
delete or ignore all "regular" project files, committing
281285
only your `output` / `build` directory.
282286

283287
---
@@ -328,7 +332,8 @@ but keep their histories separate.
328332
---
329333

330334
```bash
331-
# add an existing repository as a submodule of the current repo
335+
# add an existing repository as a
336+
# submodule of the current repo
332337
git submodule add path/to/other/repo
333338

334339
# clone a repository including all submodules

src/content/lessons/bash-scripting.md

Lines changed: 165 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -322,16 +322,34 @@ done
322322
myarray=(1 "A" 2 "B")
323323

324324
# assign to an index in an array
325-
myarray[0]=5
325+
myarray[0]="hi"
326326

327327
# print array element at index i
328328
echo ${myarray[i]}
329+
```
330+
331+
---
329332

333+
```bash
330334
# print length of array element at index i
331335
echo ${#myarray[i]}
332336

333337
# print length of array itself
334338
echo ${#myarray[@]}
339+
340+
# append items to an array
341+
myarray+=(7 "Z")
342+
```
343+
344+
---
345+
346+
Looping over each element of an array:
347+
348+
```bash
349+
colors=("red" "green" "yellow")
350+
for color in "${colors[@]}"; do
351+
echo "The traffic light is $color"
352+
done
335353
```
336354

337355
---
@@ -341,7 +359,7 @@ echo ${#myarray[@]}
341359
There are special variable that allow you to handle script arguments.
342360

343361
```bash
344-
# print number of passed-in arguments
362+
# print number of arguments passed to the script
345363
echo "$#"
346364

347365
# an array containing all arguments
@@ -371,6 +389,29 @@ my-script hello world
371389

372390
---
373391

392+
## Prompting for user input
393+
394+
Use the `read` command to block execution and allow the user to provide input through `stdin`:
395+
396+
```bash
397+
# program stops and waits for the user to input a line of text
398+
read line
399+
echo "$line"
400+
```
401+
402+
---
403+
404+
If more than one variable is provided, the line will be split into words.
405+
406+
The `-p` option allows for adding a prompt:
407+
408+
```bash
409+
read -p "Full Name: " first last
410+
echo "My name is $last, $first $last"
411+
```
412+
413+
---
414+
374415
## Handling signals
375416

376417
Use the `trap` command to execute code as a response to a system signal:
@@ -450,6 +491,27 @@ myfunc() { echo "$1 $2 $3"; }
450491

451492
---
452493

494+
## Doing math in bash
495+
496+
By default everything in the console is treated as a string.
497+
Use the `$((<expression>))` syntax to perform math.
498+
499+
```bash
500+
echo "1 + 1 = $((1+1))"
501+
# prints 1 + 1 = 2
502+
503+
# a random number between 1 and 10
504+
echo "$((RANDOM % 10 + 1))"
505+
506+
# by default $RANDOM will hold a random
507+
# number between 0 and 32767
508+
echo $RANDOM
509+
```
510+
511+
> Inside a math expression variables should **NOT** start with an `$`
512+
513+
---
514+
453515
## Linting with shellcheck
454516

455517
Shellcheck is a powerful tool that can find many mistakes and problems in your scripts.
@@ -464,3 +526,104 @@ shellcheck my-script
464526
---
465527

466528
> **Fun fact:** there is a version of the popular containerization tool Docker [written entirely in bash](https://github.com/p8952/bocker)
529+
---
530+
531+
<class-work>
532+
533+
### Create a number guessing game
534+
535+
1. Create a script called guess-num.sh
536+
2. Create a variable holding a random number between 0 and 100
537+
3. In a loop, allow the user to guess the number
538+
4. Alert the user if their guess was high or low
539+
5. Congratulate the user when they guess the number
540+
541+
</class-work>
542+
543+
<bonus-content>
544+
545+
## Complex example: interactive menu
546+
547+
The code below demonstrates a more complex script that displays an interactive menu
548+
which allows the user to choose options using the arrow keys.
549+
550+
It uses arrays, variables, functions, loops, case conditionals and math.
551+
552+
```bash
553+
#!/bin/bash
554+
555+
# Menu items
556+
options=("Install Package" "Update System" "View Logs" "Configure Settings" "Exit")
557+
558+
# Currently selected index
559+
selected=0
560+
561+
# Function to draw the menu
562+
draw_menu() {
563+
clear
564+
echo "=== Main Menu ==="
565+
echo "Use ↑/↓ arrows and Enter to select"
566+
echo ""
567+
568+
for i in "${!options[@]}"; do
569+
if [ $i -eq $selected ]; then
570+
echo "${options[$i]}" # Selected item
571+
else
572+
echo " ${options[$i]}"
573+
fi
574+
done
575+
}
576+
577+
# Function to read arrow keys
578+
read_input() {
579+
read -rsn1 key
580+
if [[ $key == $'\x1b' ]]; then
581+
read -rsn2 key
582+
fi
583+
echo "$key"
584+
}
585+
586+
# Main loop
587+
while true; do
588+
draw_menu
589+
590+
key=$(read_input)
591+
592+
case "$key" in
593+
'[A') # Up arrow
594+
((selected--))
595+
if [ $selected -lt 0 ]; then
596+
selected=$((${#options[@]} - 1))
597+
fi
598+
;;
599+
'[B') # Down arrow
600+
((selected++))
601+
if [ $selected -ge ${#options[@]} ]; then
602+
selected=0
603+
fi
604+
;;
605+
'') # Enter key
606+
clear
607+
echo "You selected: ${options[$selected]}"
608+
609+
# Handle the selection
610+
case $selected in
611+
0) echo "Installing package..." ;;
612+
1) echo "Updating system..." ;;
613+
2) echo "Viewing logs..." ;;
614+
3) echo "Configuring settings..." ;;
615+
4)
616+
echo "Goodbye!"
617+
exit 0
618+
;;
619+
esac
620+
621+
echo ""
622+
echo "Press any key to return to menu..."
623+
read -n1
624+
;;
625+
esac
626+
done
627+
```
628+
629+
</bonus-content>

0 commit comments

Comments
 (0)