So worktrees, I always thought they were a big scary things. Turns out they
are much simpler than I thought.
Myth #1 # [1]
no special setup
I thought you had to be all in or worktrees or normal git [2], but not both. When
I see folks go all in on worktrees they start with a bare repo, while its true
this is the way you go all in, its not true that this is required.
Lets make a worktree # [3]
Making a worktree is as easy as making a branch. It’s actually just a branch
that lives in another place in your filesystem.
# checkout a new worktree called compare based on main in /tmp/project
git worktree add -b compare /tmp/project main
# checkout a new worktree called compare based on HEAD in /tmp/project
git worktree add -b compare /tmp/project
# checkout a worktree from an existing feature branch in /tmp/project
git worktree add /tmp/project my-existing-feature-branch
The worktree that you create is considered a linked worktree, while the
original worktree is called the main worktree
Note that I put this in my tmp directory because I don’t expect it to live very
long, my recent use case was to compare two files after a big formatting
change. You put these where you want, bu...
Posts tagged: linux
All posts with the tag "linux"
127 posts
latest post 2026-04-18
Publishing rhythm
I write many of these posts from a 10 year old desktop that sits in my
office these days. It does a very fine job running all of the things I
need it to for my side work, but sometimes I want a mobile setup. I
don’t really want to spend the $$ on a new laptop just for the few times
I want to be somewhere else in the house. What I do have though is a
chromebook.
I’ve tried to get the chromebook into my workflow in the past, but have
failed. Much because by the time I got all of my tools up and running
in the linux vm it was taking up quite a bit of space on the device and
made it harder for others to use as a chromebook.
Today I am giving it a second try, but this time with ssh.
Checking for existing sshd # [1]
Before doing anything I checked to see if sshd is already running. Using
the following command.
sudo service ssh status
# or
pgrep -l sshd
Both returned nothing so I know that its not running.
setting up sshd # [2]
just apt install it
Next install the openssh-client and openssh-server
sudo apt install openssh-client -y
sudo apt install openssh-server -y
After this I can see that its now running by checking its status once
again.
sudo service ssh status
Gives me t...
If you have ever ran which <command> and see duplicate entries it’s likely
that you have duplicate entries in your $PATH. You can clean this up with a
one liner at the end of your bashrc or zshrc.
eval "typeset -U path"
There is GNU coreutils command called mktemp that is super handy in shell
scripts to make temporary landing spots for files so that they never clash with
another instance, and will automatically get cleaned up when you restart, or
whenever /tmp gets wiped. I’m not sure when that is, but I don’t expect it
to be long.
Making temp directories # [1]
Here are some examples of making temp directories in different places, my
favorite is mktemp -dt mytemp-XXXXXX.
# makes a temporary directory in /tmp/ with the defaul template tmp.XXXXXXXXXX
mktemp
# makes a temporary directory in your current directory
mktemp --directory mytemp-XXXXXX
# shorter version
mktemp -d mytemp-XXXXXX
# same thing, but makes a file
mktemp mytemp-XXXXXX
# makes a temporary directory in your /tmp/ directory (or what ever you have configured as your TMPDIR)
mktemp --directory --tmpdir mytemp-XXXXXX
# shorter version
mktemp -dt mytemp-XXXXXX
# same thing, but makes a file
mktemp --tmpdir mytemp-XXXXXX
# shorter version
mktemp -t mytemp-XXXXXX
Use Case # [2]
Here is a sample script that shows how to capture the tempdir as a variable and
reuse it. Here is an example of curling my bootstrap file into a temp
dir...
Once you give a branch the big D (git branch -D mybranch) its gone,
its lost from your history. It’s completely removed from your log.
There will be no reference to these commits, or will there?
TLDR # [1]
Checkout is your savior, all you need is the commit hash.
Immediate Regret # [2]
your terminal is still open
We have all done this, you give branch the big D only to realize it was
the wrong one. Don’t worry, not all is lost, this is the easiest to
recover from. When you run the delete command you will see something
like this.
❯ git branch -D new
Deleted branch new (was bc02a64).
Notice the hash is right there is the hash of your commit. You can use
that to get your content back.
git checkout -b bc02a64
git branch new
# or in one swoop checkout your new branch at the `start-point` you want
git checkout -b new bc02a64
Delayed reaction # [3]
you have closed your terminal
If you have closed your terminal, or have deleted with a gui or
something that does not tell you the hash as you run it, don’t fret, all
your work is still there (as long as you have commited). You just have
to dig it out. The reflog contains a list of all git [4] operations that
have occurred on your ...
Big announcement recently that obs studio now builds out to a flatpak,
hopefully making it easier for all of us to install, especially us near
normies that don’t regularly compile anything from source.
install flatpak # [1]
I did not have flatpak installed so the first thing I had to do was get
the flatpak command installed, and add their default repo.
sudo apt install flatpak
flatpak remote-add --if-not-exists flathub https://flathub.org/repo/flathub.flatpakrepo
Once I had flatpak, I was able to get obs installed with the following
command.
flatpak install flathub com.obsproject.Studio
Once Installed it fired right up for me with the next command they
suggested.
flatpak run com.obsproject.Studio
It Works # [2]
Pretty straightforward, following the instructions given it all worked
for me, but it was missing a lot of the plugins that the current snap
package I am using gives me (namely virtual webcam). So I am not ready
to jump onto it until I figure out how to manage my own obs plugins.
For now I think the snap is working just well enough.
Links # [3]
- flatpak setup for ubuntu [4]
- obs release notes [5]
- obs flatpak [6]
References:
[1]: #install-flatpak
[2]: #it-wo...
Anyone just starting out their vim customization journey is bound to run into this error.
E5520: <Cmd> mapping must end with <CR>
I did not get it # [1]
I’ll admit, in hindsight it’s very clear what this is trying to tell me, but
for whatever reason I still did not understand it and I just used a :
everywhere.
From the docs # [2]
If you run :h <cmd> you will see a lot of reasons why you should do it, from
performance, to hygene, to ergonomics. You will also see another clear
statement about how to use <cmd>.
E5520
<Cmd> commands must terminate, that is, they must be followed by <CR> in the
{rhs} of the mapping definition. Command-line mode is never entered.
When to map with a : # [3]
You still need to map your remaps with a : if you do not close it with a
<cr>. This might be something like prefilling a command with a search term.
nnoremap <leader><leader>f :s/search/
Otherwise use # [4]
If you can close the <cmd> with a <cr> the command do so. Your map will
automatically be silent, more ergonomic, performant, and all that good stuff.
nnoremap <leader><leader>f <cmd>s/search/Search/g<cr>
References:
[1]: #i-did-not-get-it
[2]: #from-the-docs
[3]: #when-to-map-with-a-...
One thing about moving to a tiling window manager like awesome wm or i3 is that
they are so lightweight they are all missing things like bluetooth gui’s out of
the box, and you generally bring your own. Today I just needed to connet a new
set of headphones, so I decided to just give the bluetoothctl cli a try. It
seems to come with Ubuntu, I don’t think I did anything to get it.
bluetoothctl
Running bluetoothctl pops you into a repl/shell like bah, python, or ipython.
From here you can execute bluetoothctl commands.
Here is what I had to do to connect my headphones.
# list out the commands available
help
# scan for new devices and stop when you see your device show up
scan on
scan off
# list devices
devices
paired-devices
# pair the device
pair XX:XX:XX:XX:XX:XX
# now your device should show up in the paired list
paired-devices
# connet the device
connect XX:XX:XX:XX:XX:XX
help # [1]
Here is the output of the help menu on my machine, it seems pretty straight
forward to block, and remove devices from here.
note ctrl revers to the bluetooth controller on the machine you are on, and dev
refers to a device id.
Menu main:
Available commands:
-------------------
advertise A...
Samba is an implementation of the smb protocol that allows me to setup network
shares on my linux machine that I can open on a variety of devices.
I think the homelab [1] is starting to intrigue me enought to dive into the path of
experimenting with different things that I might want setup in my own home.
One key piece of this is network storage. As I looked into nas, I realized
that it takes a dedicated machine, or one virtualized at a lower level than I
have capability for right now.
Humble Beginnings # [2]
To get goind I am going to make a directory /srv/samba/public open to anyone
on my network. I am not going to worry too much about it, I just want
something up and running so that I can learn.
Install samba, open the firewall, and edit the smb.conf
sudo apt install samba samba-common-bin
sudo ufw allow samba
sudo nvim /etc/samba/smb.conf
I added this to the end of my smb.conf
[public]
comment = public share, no need to enter username and password
path = /srv/samba/public/
browseable = yes
writable = yes
guest ok = yes
Then I made the /srv/samba/public directory and made it writable by anyone.
sudo mkdir -p /srv/samba/public
sudo setfacl -R -m "u:nobody:rwx" /srv/s...
A super useful tool when doing PR’s or checking your own work during a big
refactor is the silver searcher. Its a super fast command line based searching
tool. You just run ag "<search term>" to search for your search term. This
will list out every line of every file in any directory under your current
working directory that contains a match.
Ahead/Behind # [1]
It’s often useful to need some extra context around the change. I recently
reviewed a bunch of PR’s that moved schema from save_args to the root of the
dataset in all yaml configs. To ensure they all made it to the top level
DataSet configuraion, and not underneath save_args. I can do a search for all
the schemas, and ensure that none of them are under save_args anymore.
ag "schema: " -A 12 -B 12
References:
[1]: #aheadbehind
Installing rust in your own ansible playbook will make sure that you can
get consistent installs accross all the machines you may use, or
replicate your development machine if it ever goes down.
Personal philosophy # [1]
I try to install everything that I will want to use for more than just a
trial inside of my ansible playbook. This way I always get the same
setup across my work and home machines, and anytime I might setup a
throw away vm.
reccommended install # [2]
This is how rust reccomends that you install it on Ubuntu. First update
your system, then run their installer, and finally check that the
install was successful.
# system update
sudo apt update
sudo apt upgrade
# download and run the rust installer
curl https://sh.rustup.rs -sSf | sh
# confirm your installation is successful
rustc --version
Ansible Install # [3]
The first thing I do in my playbooks is to check if the tool is already
installed. Here I chose to look for cargo, you could also look for
rustc.
- name: check if cargo is installed
shell: command -v cargo
register: cargo_exists
ignore_errors: yes
I first check for an existing install so I can re-run my playbooks
quickly filling in only missing...
Creating a minimal config specifically for git [1] commits has made running
git commit much more pleasant. It starts up Much faster, and has all
of the parts of my config that I use while making a git commit. The one
thing that I often use is autocomplete, for things coming from elsewhere
in the tmux session. For this cmpe-tmux specifically is super
helpful.
The other thing that is engrained into my muscle memory is jj
for escape. For that I went agead and added my settings and keymap
with no noticable performance hit.
Here is the config that has taken
~/.config/nvim/init-git.vim
source ~/.config/nvim/settings.vim
source ~/.config/nvim/keymap.vim
source ~/.config/nvim/git-plugins.vim
lua require'waylonwalker.cmp'
~/.config/nvim/git-plugins.vim
call plug#begin('~/.local/share/nvim/plugged')
" cmp
Plug 'hrsh7th/nvim-cmp'
Plug 'hrsh7th/cmp-nvim-lsp'
Plug 'hrsh7th/cmp-buffer'
Plug 'hrsh7th/cmp-path'
Plug 'hrsh7th/cmp-calc'
Plug 'andersevenrud/compe-tmux', { 'branch': 'cmp' }
call plug#end()
~/.gitconfig
[core]
editor = nvim -u ~/.config/nvim/init-git.vim
References:
[1]: /glossary/git/
stow -R --simulate -vvv git
One of the first things I noticed broken in my terminal based workflow moving
from Windows wsl to ubuntu was that my clipboard was all messed up and not
working with my terminal apps. Luckily setting tmux and neovim to work with
the system clipboard was much easier than it was on windows.
First off you need to get xclip if you don’t already have it provided by your
distro. I found it in the apt repositories. I have used it between Ubuntu
18.04 and 21.10 and they all work flawlessly for me.
I have tmux setup to automatically copy any selection I make to the clipboard
by setting the following in my ~/.tmux.conf. While I have neovim open I need
to be in insert mode for this to pick up.
# ~/tmux.conf
bind -T copy-mode-vi Enter send-keys -X copy-pipe-and-cancel "xclip -i -f -selection primary | xclip -i -selection clipboard"
bind-key -T copy-mode-vi MouseDragEnd1Pane send-keys -X copy-pipe-and-cancel "xclip -selection clipboard -i"
To get my yanks to go to the system clipboard in neovim, I just added
unnamedplus to my existing clipboard variable.
# ~/.config/nvim/init.vim
set clipboard+=unnamedplus
If you need to copy something right from the terminal you can use xclip
directly. ...
I have added a hotkey to my copier template setup to quickly access all my
templates at any time from tmux. At any point I can hit <c-b><c-b>, thats
holding control and hitting bb, and I will get a popup list of all of my
templates directory names. Its an fzf list, which means that I can fuzzy
search through it for the template I want, or arrow key to the one I want if I
am feeling insane. I even setup it up so that the preview is a list of the
files that come with the template in tree view.
bind-key c-b popup -E -w 80% -d '#{pane_current_path}' "\
pipx run copier copy ~/.copier-templates/`ls ~/.copier-templates |\
fzf --header $(pwd) --preview='tree ~/.copier-templates/{} |\
lolcat'` . \
"
I’ve had this on my systems for a few weeks now and I am constantly using it
for my tils [1],
blogs [2], and my .envrc file that goes into
all of my projects to make sure that I have a virtual environment [3] installed and
running any time I open it.
[4]
References:
[1]: https://waylonwalker.com/til/
[2]: https://waylonwalker.com/archive/
[3]: /virtual-environment/
[4]: https://images.waylonwalker.com/copier-templates-tmux-popup.png
Copier allows you to run post render tasks, just like cookiecutter. These are
defined as a list of tasks in your copier.yml. They are simply shell
commands to run.
The example I have below runs an update-gratitude bash script after the
copier template has been rendered.
# copier.yml
num: 128
_answers_file: .gratitude-copier-answers.yml
_tasks:
- "update-gratitude"
I have put the script in ~/.local/bin so that I know it’s always on my
$PATH. It will reach back into the copier.yml and update the default
number.
#!/bin/bash
# ~/.local/bin/update-gratitude
current=`awk '{print $2}' ~/.copier-templates/gratitude/copier.yml | head -n 1`
new=`expr $current + 1`
echo $current
echo $new
sed -i "s/$current/$new/g" ~/.copier-templates/gratitude/copier.yml
I really appreciate that in linux anything can be scripted, including
setting the wallpaper. So everytime I disconnect a monitor I can just
rerun my script and fix my wallpaper without digging deep into the ui
and fussing through a bunch of settings.
feh --bg-scale ~/.config/awesome/wallpaper/my_wallpaper.png
I set my default wallpaper with feh using the command above.
Leaning in on feh, we can use fzf to pick a wallpaper from a directory
full of wallpapers with very few keystrokes.
alias wallpaper='ls ~/.config/awesome/wallpaper | fzf --preview="feh --bg-scale ~/.config/awesome/wallpaper/{}" | xargs -I {} feh --bg-scale ~/.config/awesome/wallpaper/{}'
I have mine alias’d to wallpaper so that I can quickly run it from
my terminal.
Converting markdown posts to pdf on ubuntu takes a few packages from the
standard repos. I had to go through a few stack overflow posts, and
nothing seemed to have all the fonts and packages that I needed to
convert markdown, but this is what ended up working for me.
Installing all the packages # [1]
sudo apt install \
pandoc \
texlive-latex-base \
texlive-fonts-recommended \
texlive-extra-utils \
texlive-latex-extra \
texlive-xetex
Using pandoc to convert markdown to a pdf # [2]
# older versions of pandoc, I needed this one on ubuntu 18.04
pandoc pages/til/convert-markdown-pdf-linux.md -o convert-markdown-pdf.pdf --latex-engine=xelatex
# newer versions of pandoc, I needed this one on ubuntu 21.04
pandoc pages/til/convert-markdown-pdf-linux.md -o convert-markdown-pdf.pdf --pdf-engine=xelatex
[3]
Here is an image of what converting this article over to a pdf looks
like. The raw markdown is
here [4].
References:
[1]: #installing-all-the-packages
[2]: #using-pandoc-to-convert-markdown-to-a-pdf
[3]: https://images.waylonwalker.com/convert-markdown-pdf-linux-result.png
[4]: https://waylonwalker.com/convert-markdown-pdf-linux.md
I recently paired up with another dev running windows with Ubuntu running in
wsl, and we had a bit of a stuggle to get our project off the ground because
they were missing com system dependencies to get going.
Straight in the terminal # [1]
Open up a terminal and get your required system dependencies using the apt
package manager and the standard ubuntu repos.
sudo apt update
sudo apt upgrade
sudo apt install \
python3-dev \
python3-pip \
python3-venv \
python3-virtualenv
pip install pipx
Using an Ansible-Playbook # [2]
I like running things like this through an ansible-playbook as it give me some
extra control and repeatability next time I have a new machine to setup.
- hosts: localhost
gather_facts: true
become: true
become_user: "{{ lookup('env', 'USER') }}"
pre_tasks:
- name: update repositories
apt: update_cache=yes
become_user: root
changed_when: False
vars:
user: "{{ ansible_user_id }}"
tasks:
- name: Install System Packages 1 (terminal)
become_user: root
apt:
name:
- build-essential
- python3-dev
- python3-pip
- python3-venv
- python3-virtualenv
- name: check is pipx installed
shell: command -v pipx
register: pipx_exists
ignore_errors: y...
Stow is an incredible way to manage your dotfiles. It works by managing
symlinks between your dotfiles directory and the rest of the system. You can
then make your dotfiles directory a git [1] repo and have it version controlled. In
my honest opinion, when I was trying to get started the docs straight into deep
detail of things I frankly don’t really care about and jumped right over how to
use it.
When using stow its easiest to keep your dotfiles directory (you may name it
what you want) in your home directory, with application directories inside of
it.
Then each application directory should reflet the same diretory structure as you
want in your home directory.
zsh # [2]
Here is a simple example with my zshrc.
mkdir ~/dotfiles
cd ~/dotfiles
mkdir zsh
mv ~/.zshrc zsh
stow --simulate zsh
You can pass in the –simulate if you wish, it will tell you if there are going
to be any more errors or not, but it wont give much more than that.
WARNING: in simulation mode so not modifying filesystem.
Once your ready you can stow your zsh application.
stow zsh
nvim # [3]
A slightly more complicated example is neovim since its diretory structure does
not put configuration files directl...