Saturday 30 December 2023

Getting started with Python in Jupyter Notebooks

So, as we get ready to start a new year, I'm tinkering with a bunch of new ( to me ) tech toys, including wrangling Python dependencies.

Having spent much of of the past year or so using pip and pyenv to manage Python dependencies, more recently, I've been looking at an alternate solution, Anaconda.

Having downloaded and installed the Mac version of Anaconda - and allowed it to install itself into ~/.zshrc ( as I use Z Shell rather than, say, Bash ), when I start a new Terminal window ( I'm using iTerm 3.4.23 on macOS 14.2.1 ), I automatically open up in a virtual environment called base 

conda env list

# conda environments:
base                  *  /Users/hayd/anaconda3

type conda

conda is a shell function from /Users/hayd/.zshrc

This also gives me access to Jupyter : -

type jupyter

jupyter is /Users/hayd/anaconda3/bin/jupyter

jupyter notebook

  _   _          _      _
 | | | |_ __  __| |__ _| |_ ___
 | |_| | '_ \/ _` / _` |  _/ -_)
  \___/| .__/\__,_\__,_|\__\___|

Read the migration plan to Notebook 7 to learn about the new features and the actions to take if you are using extensions.

Please note that updating to Notebook 7 might break some of your extensions.

[W 15:06:56.602 NotebookApp] Loading JupyterLab as a classic notebook (v6) extension.
[I 2023-12-29 15:06:56.605 LabApp] JupyterLab extension loaded from /Users/hayd/anaconda3/lib/python3.11/site-packages/jupyterlab
[I 2023-12-29 15:06:56.605 LabApp] JupyterLab application directory is /Users/hayd/anaconda3/share/jupyter/lab
[I 15:06:57.709 NotebookApp] Serving notebooks from local directory: /Users/hayd
[I 15:06:57.709 NotebookApp] Jupyter Notebook 6.5.4 is running at:
[I 15:06:57.709 NotebookApp] http://localhost:8888/?token=707355ee0dd1f8fd9bf4e7124b83d1126a024cc4606eade0
[I 15:06:57.709 NotebookApp]  or
[I 15:06:57.709 NotebookApp] Use Control-C to stop this server and shut down all kernels (twice to skip confirmation).
[C 15:06:57.711 NotebookApp]

    To access the notebook, open this file in a browser:
    Or copy and paste one of these URLs:
0.00s - Debugger warning: It seems that frozen modules are being used, which may
0.00s - make the debugger miss breakpoints. Please pass -Xfrozen_modules=off
0.00s - to python to disable frozen modules.
0.00s - Note: Debugging will proceed. Set PYDEVD_DISABLE_FILE_VALIDATION=1 to disable this validation.

which automatically opens up a browser tab: -

jupyter notebook list

Currently running servers:
http://localhost:8888/?token=707355ee0dd1f8fd9bf4e7124b8ad1126a024cc4606eade0 :: /Users/hayd

shows me the running notebook, plus it's port AND authentication token :-)

With the Jupyter server running, I quickly created a new Python3 ( pykernel ) notebook: -

and am off to the races: -

For reference, I'm working on as a coder at present, and am running through some of the Python-based prompt engineering tutorials, and wanted a place to test the generated Python code

This was of use, in terms of getting me started: -

Saturday 4 November 2023

More on macOS SMB sharing

As a follow-up to an earlier post: -

I hit this problem again and referred back to my post, and also to Dan's post: -

digging further into the firewall settings on my Mac mini

Having noticed that smbd did NOT appear in the list returned by 

/usr/libexec/ApplicationFirewall/socketfilterfw —listapps

I looked again at the firewall settings: -

and explicitly added smbd via it's path: -


and also enabled smbd via 

 /usr/libexec/ApplicationFirewall/socketfilterfw --unblockapp /usr/sbin/smbd

Incoming connection to the application is permitted

Now it looks better: -

/usr/libexec/ApplicationFirewall/socketfilterfw --listapps

ALF: total number of apps = 4

1 :  /System/Library/CoreServices/
  ( Allow incoming connections )

2 :  /Applications/
  ( Allow incoming connections )

3 :  /usr/sbin/smbd
  ( Allow incoming connections )

4 :  /System/Library/CoreServices/
  ( Allow incoming connections )

and, even better, I can access the Mac Mini via SMB from other Macs without issues

Nice !

Monday 23 October 2023

Why I can't install jq on Ubuntu 20.04

 A friend asked me why they were unable to install jq onto their Ubuntu 20.04 Linux box - which seems like a perfectly reasonable to do / ask.
So I tried ...
And failed ...
lsb_release -a
No LSB modules are available.
Distributor ID:    Ubuntu
Description:    Ubuntu 20.04.6 LTS
Release:    20.04
Codename:    focal

uname -a

Linux 5.4.0-156-generic #173-Ubuntu SMP Tue Jul 11 07:25:22 UTC 2023 x86_64 x86_64 x86_64 GNU/Linux

apt-get update && apt-get upgrade -y
apt-get install -y jq

Reading package lists... Done
Building dependency tree
Reading state information... Done
E: Unable to locate package jq

Having read the jq download page, which says, in part: -
jq is in the official Debian and Ubuntu repositories. Install using sudo apt-get install jq.

I was confused, to say the least ....

And then I remembered to check the Aptitude Package Manager's sources.list file : -

cat /etc/apt/sources.list

# See for how to upgrade to
# newer versions of the distribution.
deb focal main
# deb-src focal main restricted

## Major bug fix updates produced after the final release of the
## distribution.
deb focal-updates main
# deb-src focal-updates main restricted

## N.B. software from this repository is ENTIRELY UNSUPPORTED by the Ubuntu
## team. Also, please note that software in universe WILL NOT receive any
## review or updates from the Ubuntu security team.
# deb-src focal universe
# deb-src focal-updates universe

## N.B. software from this repository is ENTIRELY UNSUPPORTED by the Ubuntu
## team, and may not be under a free licence. Please satisfy yourself as to
## your rights to use the software. Also, please note that software in
## multiverse WILL NOT receive any review or updates from the Ubuntu
## security team.
# deb-src focal multiverse
# deb-src focal-updates multiverse

## N.B. software from this repository may not have been tested as
## extensively as that contained in the main release, although it includes
## newer versions of some applications which may provide useful features.
## Also, please note that software in backports WILL NOT receive any review
## or updates from the Ubuntu security team.
deb focal-backports main
# deb-src focal-backports main restricted universe multiverse

## Uncomment the following two lines to add software from Canonical's
## 'partner' repository.
## This software is not part of Ubuntu, but is offered by Canonical and the
## respective vendors as a service to Ubuntu users.
# deb focal partner
# deb-src focal partner

deb focal-security main
# deb-src focal-security main restricted
# deb-src focal-security universe
# deb-src focal-security multiverse

or, more specifically, looking for the Ubuntu Universe repository : -

cat /etc/apt/sources.list|grep -i universe

## team. Also, please note that software in universe WILL NOT receive any
# deb-src focal universe
# deb-src focal-updates universe
# deb-src focal-backports main restricted universe multiverse
# deb-src focal-security universe

which showed that universe wasn't enabled ...

So I backed up the existing /etc/apt/source.list file: -

cp /etc/apt/sources.list /etc/apt/sources.list.ORIG
and then added the universe repo: -
cat <<EOF >> /etc/apt/sources.list
deb focal universe
deb focal-updates universe
deb focal-security universe

and tried again: -

apt-get update && apt-get install -y jq

Reading package lists... Done
Building dependency tree
Reading state information... Done
The following additional packages will be installed:
  libjq1 libonig5
The following NEW packages will be installed:
  jq libjq1 libonig5
0 upgraded, 3 newly installed, 0 to remove and 0 not upgraded.
Need to get 313 kB of archives.
After this operation, 1,062 kB of additional disk space will be used.
Get:1 focal/universe amd64 libonig5 amd64 6.9.4-1 [142 kB]
Get:2 focal-updates/universe amd64 libjq1 amd64 1.6-1ubuntu0.20.04.1 [121 kB]
Get:3 focal-updates/universe amd64 jq amd64 1.6-1ubuntu0.20.04.1 [50.2 kB]
Fetched 313 kB in 1s (440 kB/s)
Selecting previously unselected package libonig5:amd64.
(Reading database ... 108600 files and directories currently installed.)
Preparing to unpack .../libonig5_6.9.4-1_amd64.deb ...
Unpacking libonig5:amd64 (6.9.4-1) ...
Selecting previously unselected package libjq1:amd64.
Preparing to unpack .../libjq1_1.6-1ubuntu0.20.04.1_amd64.deb ...
Unpacking libjq1:amd64 (1.6-1ubuntu0.20.04.1) ...
Selecting previously unselected package jq.
Preparing to unpack .../jq_1.6-1ubuntu0.20.04.1_amd64.deb ...
Unpacking jq (1.6-1ubuntu0.20.04.1) ...
Setting up libonig5:amd64 (6.9.4-1) ...
Setting up libjq1:amd64 (1.6-1ubuntu0.20.04.1) ...
Setting up jq (1.6-1ubuntu0.20.04.1) ...
Processing triggers for man-db (2.9.1-1) ...
Processing triggers for libc-bin (2.31-0ubuntu9.12) ...

and now things are happy: -

jq --version


cat ~/family.json | jq

  "friends": [
      "givenName": "Dave",
      "familyName": "Hay"
      "givenName": "Homer",
      "familyName": "Simpson"
      "givenName": "Marge",
      "familyName": "Simpson"
      "givenName": "Lisa",
      "familyName": "Simpson"
      "givenName": "Bart",
      "familyName": "Simpson"

Thursday 15 June 2023

macOS to macOS File Sharing - Don't work, try The IT Crowd

 I use File Sharing between two Macs on the same network, both running the latest macOS 13.4 Ventura.

For some strange reason I wasn't able to access one Mac - a Mini - from the other - a MacBook Pro.

As is always the case, the internet solved it for me: -

Fix File Sharing Not Working in MacOS Ventura

TL;DR; turn it off, and on again

Yes, The IT Crowd strikes again

Having said that, Dan Moren, he of Six Colours, acclaimed author AND MacBreak Weekly host, deserves full thanks for directing me to macOS' built-in firewall tool: -

/usr/libexec/ApplicationFirewall/socketfilterfw --listapps

Solving a file sharing mystery: Why one Mac can’t see another 

Whilst the TIOAOA trick worked this time, who knows what I'll need next time ...

Monday 22 May 2023

On the subject of aliases ...

I'm a super-massive fan of time/labour saving devices, and that goes for command-line tips n' tricks to save me: -

(a) typing more stuff

(b) looking in my notes to remember what I need, in order to type more stuff

Therefore, I've finally got around to creating an alias to create a new branch in a GitHub repo that I've cloned to my Mac.

I've added this alias to ~/.zprofile: -

gitbranch='git fetch origin && git rebase origin/master && git checkout master; git checkout -b $1'

so now I just need to type: -

gitbranch foobar

or: -

gitbranch snafu

in order to create a new branch ...

Which is nice.

Using 1Password to store API keys ...

 Following on from my earlier post: -

Wow, why have I not been using 1Password for my SSH keys before today ? 

I've got a little further, with various API keys now stored in my 1Password vault

This is far simpler, in that the vault entry, of type API Credential, only needs to have a name/title e.g. IBM Cloud API Key and a credential, the actual API key itself.

With that in place, I've then setup an alias to retrieve/display the API key: -

apikey='export APIKEY=$(op item get "IBM Cloud" --field credential) && echo $APIKEY'

in ~/.zprofile, meaning that I just need to run the "command" apikey to ... see my API key.

I will, of course, be leveraging the same API keys in various other scripts/aliases, including things that login to IBM Cloud etc.

Saturday 20 May 2023

Wow, why have I not been using 1Password for my SSH keys before today ?

 As an avid user of 1Password, I've only really just delved into the Command-Line Interface (CLI), including the ability to create AND use SSH keys.

I'm running on macOS 13.4 and, as per the documentation - Manage SSH Keys - I've installed the BETA version of the op command: -


downloaded from here 

I'm also running 1Password for Mac 8.10.6 (81006027) and, having configured the SSH Agent and the Command-Line Interface (CLI) options via Settings > Developer : -

1Password Developer pane showing SSH Agent and CLI settings

and then generate a new SSH key: -

op ssh generate --title "SSH Key - 20 May 2023"

The key then appeared under a new 1Password category - SSH Keys - from where I could select the public key and add it to the ~/.ssh/authorized_keys file on two of my target Ubuntu boxes

This has all made life much easier on the Mac, via iTerm etc. where my SSH config is WAY simpler: -

cat ~/.ssh/config

Host *
  IdentityAgent "~/Library/Group Containers/"

Even better, I was able to quickly add the public key to GitHub's SSH Keys page via the New SSH Key button, which immediately prompted to retrieve the new key - SSH Key - 20 May 2023 - from the 1Password vault ...

Which is nice

Friday 19 May 2023

Today I Learned - how to deal with Shell Check SC2086

So, technically I learned this yesterday but 🤷‍♀️

As part of our CI/CD testing, we run shellcheck  against our shell scripts, and saw the following: -

   ^----^ SC2086 (info): Double quote to prevent globbing and word splitting.

for a piece of code that referenced a variable e.g. : -

echo $FILES

The shellcheck Wiki covers this: -

SC2086 – ShellCheck Wiki

and suggests that $FILES be wrapped in double quotes e.g. : -

echo "$FILES"

So far, so good

However, the code in question was actually a variable containing more than one element e.g. : -

FILES="a.txt b.txt c.txt"

so the next line in the script which leveraged the values within the $FILES variable: -

ls "$FILES"

fails with: -

ls: a.txt b.txt c.txt: No such file or directory

Thinking more about this, this kinda made sense i.e. we're treating the values within the $FILES variable as elements within an array, but we're not actually treating the variable as an array, by incrementing through the elements by an index.

The Wiki does reference this: -

Using that as inspiration, I updated the script: -

read -ra files <<<"${FILES}"
ls "${files[@]}"

In essence, this is creating a "real" array from the $FILES variable, and then we're incrementing the index using [@] 

To be clear, I also took inspiration from: -

How to be explicit about intentional word splitting?

and this is my demo / test script: -

#! /bin/bash
# Set variable
FILES="a.txt b.txt c.txt"
echo "Works, but breaks shellcheck"
echo "Fails, but passes shellcheck"
ls "$FILES"
echo "Works, and passes shellcheck"
read -ra files <<<"${FILES}"
ls "${files[@]}"

which, when I run it, does this: -


Works, but breaks shellcheck

a.txt b.txt c.txt

Fails, but passes shellcheck

ls: a.txt b.txt c.txt: No such file or directory

Works, and passes shellcheck

a.txt b.txt c.txt

Finally, for now, there's a great shellcheck plugin for VS Code: -

ShellCheck for Visual Studio Code

and, for the record, the shellcheck project is available on GitHub

Thursday 27 April 2023

Why oh why did I forget vimdiff ?

 Whilst trying to compare two branches of a GitHub repo on my Mac, I was using diff to compare/contrast specific files, and trying to parse the differences.

And then I remembered vimdiff

Source: Linux `Vimdiff` Command – How to Compare Two Files in the Command Line 

PS Using freeCodeCamp for the above image, as I don't want to reveal my sources ( i.e. source code )

Unix - redirecting output to /dev/null

In the past, I've used redirection to send output to /dev/null such as: -

foobar 2> /dev/null

where foobar is a non-existent command/binary, but I want the error output ( stderr ) such as: -

zsh: command not found: foobar

or: -

foobar: command not found

to be "hidden"

Similarly, I've used redirection to send "pukka" output ( stdout ) to also go to /dev/null e.g. : -

uptime 1> /dev/null

However, I'd not seen the simple way to do both in one fell swoop: -

foobar &> /dev/null

uptime &> /dev/null

where the ampersand ( & ) is used to send BOTH stdout and stderr to /dev/null

As ever, which is nice

IBM Container Registry - searching and formatting

 So, when querying images that have been pushed to a namespace within IBM Container Registry, one can format the output to only return certain columns such as repository (image) name and tag.

Who knew ?

Well, the authors of the documentation did, apparently :-)

Formatting and filtering the CLI output

For example: -

ibmcloud cr images --format "{{ .Repository }}:{{ .Tag }}"


Other examples, from the doc, include: -

ibmcloud cr image-list --format "{{ if gt .Size 1000000 }}{{ .Repository }}:{{ .Tag }} {{ .SecurityStatus.Status }}{{end}}"

ibmcloud cr image-digests --format '{{if not .Tags}}{{.Repository}}@{{.Digest}}{{end}}'

ibmcloud cr image-inspect ibmliberty --format "{{ .ContainerConfig.Labels }}"


Which is nice!


And, bringing two posts together, I can report the created date AND format it from Epoch time: -

ic cr images --format "{{ .Repository }}:{{ .Tag }}:{{ .Created }}" | awk 'BEGIN { FS = ":"} ; {$3 = strftime("%c", $3)} 1'

Friday 21 April 2023

Today I Learned - Munging Epochs using awk

So today I had a requirement to convert some Epoch-formatted dates, located in a CSV file, into human-readable dates...

So today I learned about awk vs. gawk, and the strftime() function ...

I also learned that awk on macOS isn't the same as "real" Gnu awk ( aka gawk ), hence the need for gawk ...

I started by installing gawk: -

brew install gawk

and then updated my PATH to reflect it: -


Using an example of my data: -

cat file.txt


which is WAY simpler than my real data, I was then able to munge it using awk ( or, really, gawk ) : -

awk 'BEGIN { FS = ","} ; {$1 = strftime("%c", $1)} 1' file.txt

which returns: -

Fri 14 Apr 16:35:14 2023
Thu 20 Apr 12:39:47 2023
Thu 20 Apr 13:14:13 2023
Mon 17 Apr 07:29:09 2023

I'd previously done much the same using Excel, via a formula: -


where cell F17 contained the Epoch-formatted date

But scripts are so much more fun ...

Monday 17 April 2023

IBM Cloud and JQ - more querying fun

 A colleague laid down a challenge - well, he didn't actually lay it down, he merely posted a single-line script that used awk and sed and grep - so I decided to build a better mousetrap ...

The requirement ... to query one's IBM Cloud account for Kubernetes (K8s) clusters, in this case leveraging the IBM Kubernetes Service (IKS) offering, and report the cluster name and the flavour ( flavor to our US friends )

Here is up with what I ended: -

for i in $(ic cs cluster ls --provider vpc-gen2 --output JSON | jq -r '.[].name'); do echo "Cluster Name:" $i; echo -n "Flavor: "; ic cs workers --cluster $i --output JSON | jq -r '.[].flavor'; done

which resulted in: -

Cluster Name: davehay-14042023

Flavor: bx2.4x16

Cluster Name: davehay-15042023

Flavor: bx2.4x16

In essence, I list the clusters in the account ( across all regions ), specifically those using the Virtual Private Cloud Generation 2 ( vpc-gen2 ) provider, grab and output the name, and then use the name to inspect the cluster and report on it's flavor ( sic ).

Rather than using awk and sed and grep etc. I chose to use jq, working on the assumption that all of our engineers will have that installed as it's a ubiquitous tool these days.

Tuesday 4 April 2023

IBM Cloud CLI - Debugging

From this: -
we have some rather useful debugging env vars such as: -



TIL: FuzzyFinder - fzf - and jq

Today I learned ( well, actually it was yesterday but who's counting days ? ) about fzf in the context of using it to test JQ expressions.

The revelation came from Julia Evans, author of WizardZines, aka b0rk, about whom I've written before.

She'd mentioned the use of fzf and jq in a post on Mastodon: -

so I had to try it out ...

Install fzf

brew install fzf

Create a JSON document

cat << EOF > the_simpsons.json
        "givenName": "Maggie",
        "familyName": "Simpson"
        "givenName": "Lisa",
        "familyName": "Simpson"
        "givenName": "Marge",
        "familyName": "Simpson"
        "givenName": "Homer",
        "familyName": "Simpson"
        "givenName": "Bart",
        "familyName": "Simpson"

Fire up fzf

echo '' | fzf --preview 'jq {q} < the_simpsons.json'

Tinker with various jq queries


Tuesday 21 February 2023

Reading up on the differences between Zsh and Bash

Typically, when writing self-documenting scripts, especially those used during a demonstration, I'd add a command such as: -

read -p "Press [Enter] to continue"

However, using Zsh on macOS 13.2.1 Ventura, I saw: -

read: -p: no coprocess

If I skipped the -p I saw: -

zsh: not an identifier: Press [Enter] to continue

when I actually pressed the Enter key

As ever, the internet answered my cry for help

ZSH: Read command fails within bash function "read:1: -p: no coprocess"

So now I have this: -

ibmcloud cs cluster ls

read "?Press [Enter] to continue"

which rightly prompts: -

Press [Enter] to continue

Monday 6 February 2023

Fun and games with Docker login on macOS

I've been around the houses with Docker Desktop, Podman and Docker via Homebrew on my Mac over the past few months

I saw something curious this morning, whilst trying to log into IBM Container Registry 

ic cr login

Logging 'docker' in to ''...


Failed to 'docker login' to '' with error: Error saving credentials: error storing credentials - err: docker-credential-desktop resolves to executable in current directory (./docker-credential-desktop), out: ``

I then tried the same auth process using docker login 

docker login --username iamapikey

but with the same effect: -


Error saving credentials: error storing credentials - err: docker-credential-desktop resolves to executable in current directory (./docker-credential-desktop), out: ``

In case I was missing something, I even tried the Docker Creds Helper: -

brew install docker-credential-helper

but to no avail.

Finally, in desperation, I nuked my Docker credentials file - which is a TERRIBLE thing imho 

rm ~/.docker/config.json

and tried again: -

docker login --username iamapikey


Login Succeeded

Even better, now that I'd installed the creds helper - which caches the creds in the macOS Keychain, the config.json is somewhat cleaner: -

cat ~/.docker/config.json


"auths": {

"": {}


"credsStore": "osxkeychain"


Better still, the IBM Cloud CLI is also happy: -

ic cr login

Logging 'docker' in to ''...

Logged in to ''.


Thursday 2 February 2023

Removing filenames with special characters - a reminder

I've written this down somewhere before but ...

I have a file that I created, by mistake, by abusing the target during a scp command

ls -altrc

-rw-r--r-- 1 root root 2541 Feb  2 02:15 '~'

and I wanted to delete it - but it has weird characters in the file name

This to the rescue: -

rm -v -- '~'

removed '~'

Wednesday 1 February 2023

Reminder to self - check out Finch

From this: -

Today we are happy to announce a new open source project, Finch. Finch is a new command line client for building, running, and publishing Linux containers. It provides for simple installation of a native macOS client, along with a curated set of de facto standard open source components including Lima, nerdctl, containerd, and BuildKit. With Finch, you can create and run containers locally, and build and publish Open Container Initiative (OCI) container images.

Introducing Finch: An Open Source Client for Container Development

a friend had recommended that I check out Finch, so it's definitely on my personal to-do list.

It's on GitHub and Slack 

Monday 16 January 2023

Go modules and forks

I'm tinkering with a Go project ( let's call it foobar ), which has a dependency upon yet another Go project ( let's call it snafu )  in the same organisation.

For the moment, I've got a fork of snafu in my own org - david-hay - and wanted to update go.mod in the foobar project to leverage it.

I knew I had to update go.mod either manually or use go mod edit --replace source=target but couldn't get past the exception: -

go: unversioned new path must be local directory

It turned out, as ever, that I was holding it wrong ...

I needed to explicitly provide a "version" - in this context, that was a branch e.g. main at which to point the target during go mod edit --replace like this: -

go mod edit --replace

In other words, the right-hand side of the --replace directive needed to include four things: -

- domain e.g.

- organization e.g. david-hay

- project/repo e.g. snafu

- branch e.g. main

like this: -


replace => main

When I then ran go mod tidy, this went off to GitHub and pulled down the latest release from that branch in my fork: -

go: downloading v1.11.39-0.20230116121922-46267d910e38

and updated go.mod with: -

replace => v1.11.39-0.20230116121922-46267d910e38

In other words, it replaced the branch with the release ... which is nice

With thanks to this: -

Pointing to a fork of a Go module

Friday 13 January 2023

Fun with Git and branching

In very brief terms, I hit an issue last week where I'd created four branches in a repo, having cloned the main branch of the upstream repo.

Therefore, I'd done something like this: -

git clone -b main

cd ~/foobar

git fetch origin && git rebase origin/main

to bring the main branch down to my Mac.

I'd then created my first branch: -

git branch dave1

git switch dave1

and added/changed some code, committed it, and pushed my new branch upstream.

I then went ahead and created a second branch: -

git branch dave2

git switch dave2

git fetch origin && git rebase origin/main

and again added/changed some code, committed it, and pushed the new branch upstream

All seemed fine ...

And I did the same for two more branches - dave3 and dave4 - with a PR for each branch being reviewed/approved and merged into main.

And then I found, when merging in separate Pull Request, that my changes from dave2 overwrote the changes made in dave1.

Which was weird....

A colleague helped explain ...

I see the 4 PRs were created from a shared branch instead of independently being created from main. That could explain the unexpected behavior where they kept rewriting each other. 

He went onto explain how to avoid the issue ...

When you run git checkout -b branchname it creates a branch branching off of your current branch.

I am used to running git checkout main; git checkout -b branchname to ensure my branches are direct branches off of main. That helps rebase them based on other PRs merging to main.

which worked a treat

So, now I've learned this, and am trying hard to add this to my "muscle memory" ...

git clone -b main

cd foobar

git fetch origin && git rebase origin/main

git checkout main; git checkout -b dave1


We shall see if that sticks ....

Note to self - use kubectl to query images in a pod or deployment

In both cases, we use JSON ... For a deployment, we can do this: - kubectl get deployment foobar --namespace snafu --output jsonpath="{...