2026
BIN
src/img/2026/bfl-silk-handspun.jpg
Normal file
|
After Width: | Height: | Size: 305 KiB |
BIN
src/img/2026/charlie-alpaca-handspun.jpg
Normal file
|
After Width: | Height: | Size: 131 KiB |
BIN
src/img/2026/coral-reef-handspun.jpg
Normal file
|
After Width: | Height: | Size: 90 KiB |
BIN
src/img/2026/cormorant.jpg
Normal file
|
After Width: | Height: | Size: 82 KiB |
BIN
src/img/2026/crow-print.jpg
Normal file
|
After Width: | Height: | Size: 545 KiB |
BIN
src/img/2026/crow.jpg
Normal file
|
After Width: | Height: | Size: 55 KiB |
BIN
src/img/2026/dyed-fiber.jpg
Normal file
|
After Width: | Height: | Size: 514 KiB |
BIN
src/img/2026/fire-ice-handspun.jpg
Normal file
|
After Width: | Height: | Size: 92 KiB |
BIN
src/img/2026/gold-handspun.jpg
Normal file
|
After Width: | Height: | Size: 126 KiB |
BIN
src/img/2026/goldeneye-tail.jpg
Normal file
|
After Width: | Height: | Size: 108 KiB |
BIN
src/img/2026/horsetail.jpg
Normal file
|
After Width: | Height: | Size: 173 KiB |
BIN
src/img/2026/orion-handspun.jpg
Normal file
|
After Width: | Height: | Size: 94 KiB |
BIN
src/img/2026/plant-handspun.jpg
Normal file
|
After Width: | Height: | Size: 482 KiB |
BIN
src/img/2026/rambouillet-handspun.jpg
Normal file
|
After Width: | Height: | Size: 65 KiB |
BIN
src/img/2026/ruby-alpaca-handspun.jpg
Normal file
|
After Width: | Height: | Size: 120 KiB |
BIN
src/img/2026/spinners-dream-handspun.jpg
Normal file
|
After Width: | Height: | Size: 123 KiB |
BIN
src/img/2026/spoonfairies-provider.png
Normal file
|
After Width: | Height: | Size: 36 KiB |
@ -6,9 +6,6 @@ image:
|
|||||||
tags:
|
tags:
|
||||||
- reference
|
- reference
|
||||||
- software
|
- software
|
||||||
- some
|
|
||||||
- more
|
|
||||||
- tags
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## problem statement
|
## problem statement
|
||||||
|
|||||||
11
src/posts/2026/2026-01-05-orion-handspun.md
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
---
|
||||||
|
title: orion handspun
|
||||||
|
image:
|
||||||
|
src: 2026/orion-handspun.jpg
|
||||||
|
alt: "3 skeins of handspun yarn, 1 large and 2 small. One of the small skeins is a little more inconsistent weight than the other two - this one was spun on drop spindle about 2 years ago. The other two are about a sport or maybe a DK weight. All three are a gold colorway with tiny hints of orange and a pale light green."
|
||||||
|
tags:
|
||||||
|
- gallery
|
||||||
|
- yarn
|
||||||
|
---
|
||||||
|
|
||||||
|
Fiber: Merino/silk 70/30 from [Jakira Farms](https://www.etsy.com/shop/JakiraFarms){target="_blank" rel="external"} in colorway Orion
|
||||||
556
src/posts/2026/2026-01-07-intro-to-git.md
Normal file
@ -0,0 +1,556 @@
|
|||||||
|
---
|
||||||
|
title: an intro to git
|
||||||
|
image:
|
||||||
|
src: 2026/goldeneye-tail.jpg
|
||||||
|
alt: "Image unrelated to post. The tail of a diving duck pokes out from the water with a small splash."
|
||||||
|
tags:
|
||||||
|
- reference
|
||||||
|
- software
|
||||||
|
---
|
||||||
|
|
||||||
|
alrighty, this one's a real doozy. Strap in.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
<!-- TOC -->
|
||||||
|
|
||||||
|
- [versioning](#versioning)
|
||||||
|
- [problem statement](#problem-statement)
|
||||||
|
- [what is git?](#what-is-git)
|
||||||
|
- [where can I use git?](#where-can-i-use-git)
|
||||||
|
- [what is a CLI?](#what-is-a-cli)
|
||||||
|
- [where can I use the git CLI?](#where-can-i-use-the-git-cli)
|
||||||
|
- [git for Windows](#git-for-windows)
|
||||||
|
- [WSL](#wsl)
|
||||||
|
- [a few terminal operations](#a-few-terminal-operations)
|
||||||
|
- [edit files](#edit-files)
|
||||||
|
- [git version](#git-version)
|
||||||
|
- [a few handy settings](#a-few-handy-settings)
|
||||||
|
- [git going](#git-going)
|
||||||
|
- [git init](#git-init)
|
||||||
|
- [git clone](#git-clone)
|
||||||
|
- [git status](#git-status)
|
||||||
|
- [branch main](#branch-main)
|
||||||
|
- [no commits / nothing to commit](#no-commits--nothing-to-commit)
|
||||||
|
- [commits and history](#commits-and-history)
|
||||||
|
- [git log](#git-log)
|
||||||
|
- [creating a commit](#creating-a-commit)
|
||||||
|
- [the staging area](#the-staging-area)
|
||||||
|
- [git add](#git-add)
|
||||||
|
- [git commit](#git-commit)
|
||||||
|
- [checking our work](#checking-our-work)
|
||||||
|
- [changes to existing files](#changes-to-existing-files)
|
||||||
|
- [git restore](#git-restore)
|
||||||
|
- [git revert](#git-revert)
|
||||||
|
- [git remote](#git-remote)
|
||||||
|
- [git fetch and git pull](#git-fetch-and-git-pull)
|
||||||
|
- [git push, take one](#git-push-take-one)
|
||||||
|
- [authentication](#authentication)
|
||||||
|
- [SSH keys](#ssh-keys)
|
||||||
|
- [creation](#creation)
|
||||||
|
- [an alias...](#an-alias)
|
||||||
|
- [and a function](#and-a-function)
|
||||||
|
- [SSH keys and the remote](#ssh-keys-and-the-remote)
|
||||||
|
- [git push, take two](#git-push-take-two)
|
||||||
|
- [summary](#summary)
|
||||||
|
|
||||||
|
<!-- /TOC -->
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## versioning
|
||||||
|
|
||||||
|
have you ever tried to revert to a previous version of a document in MS Office or Google Docs and found that your revision history is cluttered with small changes that by all rights should be grouped into one set of edits, but they aren't, and it's tedious to pick through all the versions?
|
||||||
|
|
||||||
|
or, more uniquely and/or uncommonly:
|
||||||
|
|
||||||
|
- you've been using Google's named versions, but you're [out of named versions (you can have 40 per doc, or 15 per spreadsheet)](https://support.google.com/docs/answer/190843#zippy=%2Ccreate-a-named-version){target="_blank" rel="external"}, so you'll have to start going back and deleting named versions, and isn't that just a pain?
|
||||||
|
- you're using MS Office, but [your file isn't in OneDrive, so there's no version history at all](https://support.microsoft.com/en-us/office/view-previous-versions-of-office-files-5c1e076f-a9c9-41b8-8ace-f77b9642e2c2){target="_blank" rel="external"}? Or maybe it *is* in OneDrive, but you were offline, so too many changes got jumbled into one big edit when you next went online?
|
||||||
|
|
||||||
|
or, websites. Maybe you're building something in Squarespace and find out that [in current versions of Squarespace, it doesn't support version history.](https://forum.squarespace.com/topic/239030-roll-site-back-to-previous-version-changes/){target="_blank" rel="external"}.
|
||||||
|
|
||||||
|
## problem statement
|
||||||
|
|
||||||
|
I started writing this to help a friend. She's getting started with a website, and we're using the static site generator [11ty](https://www.11ty.dev/){target="_blank" rel="external"} as she wants to have a lot of easy-to-write posts. She needs a single-user workflow that allows her to publish her website without hosting it herself, and that's the use case where this was born.
|
||||||
|
|
||||||
|
this walkthrough is best suited for people who want to use `git` in single-person projects, or perhaps with one or two other close collaborators. There's quite a few topics it doesn't cover that are vitally important in large collaborative projects, such as **branching** and **merging**.
|
||||||
|
|
||||||
|
this walkthrough also focuses on the "happy path," without much discussion of troubleshooting. I may write more on the topic in the future, but we're already over *4,500 words*, so we're calling it a day.
|
||||||
|
|
||||||
|
finally, I wrote this walkthrough primarily with knowledge from using **WSL** [more on this later] on **Windows** and with **Zed** as my text editor. While I've tried to cover my bases with other OSes and options, there's a solid chance I'm missing things!
|
||||||
|
|
||||||
|
that all said, let's get (git?) into it!
|
||||||
|
|
||||||
|
## what is git?
|
||||||
|
|
||||||
|
`git` is a *version control system*. We can use it to track changes we make to a set of files.
|
||||||
|
|
||||||
|
> tip: it's important to understand that despite the examples of MS Office and Google Docs above, `git` *isn't useful* with word documents. `git` shines with plain text files - .txt, .md, or basically any type of code.
|
||||||
|
|
||||||
|
### where can I use git?
|
||||||
|
|
||||||
|
many, many tools interact with `git`:
|
||||||
|
|
||||||
|
- a lot of modern text editors have graphical user interfaces (GUIs) that let you perform `git` operations, like [VSCode](https://code.visualstudio.com/docs/sourcecontrol/overview){target="_blank" rel="external"}, [Zed](https://zed.dev/docs/git){:target="_blank"}, or [Sublime Text](https://www.sublimetext.com/docs/git_integration.html){:target="_blank"}
|
||||||
|
- there are [standalone `git` GUIs](https://git-scm.com/tools/guis){target="_blank" rel="external"}
|
||||||
|
- and many `git` users use the `git` command line interface (CLI), which is fully text-based
|
||||||
|
|
||||||
|
today we're going to talk about the `git` CLI... technically. But **don't let that scare you** - we'll talk about *concepts* and *actions* that can be applied to other `git` interfaces as well.
|
||||||
|
|
||||||
|
#### what is a CLI?
|
||||||
|
|
||||||
|
a CLI a way to interact with your computer and with software in text-only form. Rather than using the mouse and clicking on things, you type in commands and see output.
|
||||||
|
|
||||||
|
### where can I use the git CLI?
|
||||||
|
|
||||||
|
if you want to use the `git` CLI, you'll need a terminal. You've got a couple options here:
|
||||||
|
|
||||||
|
- on Linux or Mac, you should have one built in! This is the easy path, congrats :) Even better, `git` generally ships with these systems, so there's no installation required. Search for an application called 'Terminal' or similar
|
||||||
|
- note that I don't have a Mac and have never used one. I can't guarantee that everything operates the same over there - there may be discrepancies I don't know about
|
||||||
|
- on Windows, there's two options
|
||||||
|
- [`git` for Windows](https://gitforwindows.org/){target="_blank" rel="external"} packages a Linux-like terminal with a `git` GUI. This may be slightly friendlier for people who aren't at all familiar with Linux. If choosing `git` for Windows, [see my installation instructions below](#git-for-windows)
|
||||||
|
- I use [Windows Subsystem for Linux, or WSL](https://learn.microsoft.com/en-us/windows/wsl/install){target="_blank" rel="external"}, which gives you a Linux distribution within Windows. It's pretty smooth sailing at this point, but there's some idiosyncracies to conquer - like the fact that your *Windows* files and your *Linux* files are stored in different places. If choosing WSL, [see my usage notes below](#wsl)
|
||||||
|
- both of the Windows options listed work with [Windows Terminal](https://apps.microsoft.com/detail/9n0dx20hk701){target="_blank" rel="external"} which offers a nicer-looking terminal experience than the basic command prompt. If you're going to keep working with what you set up today, I recommend it!
|
||||||
|
|
||||||
|
#### git for Windows
|
||||||
|
|
||||||
|
on the "Releases" page, scroll down to "Assets" and pick the `.exe` file.
|
||||||
|
|
||||||
|
during installation, you'll be asked to choose some things by the installer. Here's my recommendations:
|
||||||
|
|
||||||
|
1. if choosing to install Windows Terminal, check 'Add a Git Bash Profile to Windows Terminal' on the first options page
|
||||||
|
1. **default editor:** *don't use vim.* Pick something you have installed - it can just be Notepad - or you can use `nano,` an in-terminal editor
|
||||||
|
1. **initial branch name:** choose the 'Override' option and leave it set to "main"
|
||||||
|
1. **everything else:** keep the recommended choices
|
||||||
|
|
||||||
|
you can open `git` for Windows via the start menu by searching for 'git bash.' If you chose to install Windows Terminal, one of the dropdown options will be for a new tab will be 'Git Bash.'
|
||||||
|
|
||||||
|
#### WSL
|
||||||
|
|
||||||
|
while *installing* WSL is a single command, here's a couple notes about getting started once *inside* WSL:
|
||||||
|
|
||||||
|
- don't be concerned that you can't see anything when you type or paste your password! Since it's sensitive information, this is intentional. You'll notice this pattern a couple of times while following this walkthrough
|
||||||
|
- `Ctrl+C` and `Ctrl+V` won't work like they do on Windows. If you want to copy/paste, right-click (there won't be a context menu, it'll just happen)
|
||||||
|
- if you're downloading a text editor like the ones mentioned above, you'll still follow the *Windows* instructions
|
||||||
|
|
||||||
|
you'll also need to be careful of a few things regarding text editors to make them work with WSL:
|
||||||
|
|
||||||
|
1. if you install VSCode, you'll need to add the [remote development extension pack](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.vscode-remote-extensionpack){target="_blank" rel="external"}
|
||||||
|
1. if you install Zed, you'll need to check "Add to PATH (requires shell restart)" in the installer, then restart your terminal as noted
|
||||||
|
- there's a single setting in Zed to disable all AI settings: **Settings > AI > General > Disable AI**
|
||||||
|
1. I don't recommend installing Sublime Text if using WSL, because summoning it from within WSL is a little more complicated than either of the two above, and I found when I [reviewed editors](/comparing-text-editors) that it struggled with some file operations in WSL
|
||||||
|
|
||||||
|
you *must* start your editor of choice *within WSL*. Don't use the Windows start menu! Instead, you'll type `code .` or `zed .` (note the `.`) while in WSL.
|
||||||
|
|
||||||
|
you can open WSL via the start menu by searching for 'WSL.' If you chose to install Windows Terminal, one of the dropdown options for a new tab will be your WSL distribution, usually 'Ubuntu.'
|
||||||
|
|
||||||
|
#### a few terminal operations
|
||||||
|
|
||||||
|
here's three vital terminal commands:
|
||||||
|
|
||||||
|
- `pwd` **prints the working (current) directory**. A lot of terminals will just *show* you what your current directory on every line, but if they don't, try `pwd`.
|
||||||
|
|
||||||
|
> tip: directory is just another word for folder
|
||||||
|
|
||||||
|
- `cd` lets us **change directories**. If we type *only* `cd`, we'll be brought back to the home directory; if we provide a directory path, we'll be taken to the provided directory
|
||||||
|
- `ls` **lists** files in the current directory (including other directories)
|
||||||
|
|
||||||
|
#### edit files
|
||||||
|
|
||||||
|
we'll want to edit files, right? How do we open our editor from the terminal?
|
||||||
|
|
||||||
|
there's usually a terminal command for the editor. For VSCode, it's `code`; for Zed, it's `zed`. If we want to open the *current directory* in our editor of choice (and we do!), we'll write `<editor command> .` (note the `.`), where `.` means "the current directory."
|
||||||
|
|
||||||
|
## git version
|
||||||
|
|
||||||
|
let's check that you have git installed with `git version`. You might see something like `git version 2.34.1` printed out in response. If you don't get a version number, but instead get an error saying you don't have `git`, [install `git`](https://git-scm.com/install){target="_blank" rel="external"}.
|
||||||
|
|
||||||
|
### a few handy settings
|
||||||
|
|
||||||
|
before we really start, we're going to set a few basics to make it easier for ourselves.
|
||||||
|
|
||||||
|
```sh
|
||||||
|
# skip this one if you installed git for windows
|
||||||
|
# this means that if git wants us to edit something,
|
||||||
|
# it'll open in the built-in terminal editor 'nano'
|
||||||
|
# the default is vim, which can be pretty unfriendly to newcomers
|
||||||
|
# nano, on the other hand, will tell you how to do basic
|
||||||
|
# operations at the bottom of the editor
|
||||||
|
git config --global core.editor nano
|
||||||
|
|
||||||
|
# this uses the autocorrect
|
||||||
|
# the value specifies how many *tenths* of a second
|
||||||
|
# so 10 => 1 second
|
||||||
|
git config --global help.autocorrect 10
|
||||||
|
|
||||||
|
# skip this one if you installed git for windows
|
||||||
|
# the default branch name is "master" due to older computer terminology
|
||||||
|
# older language used to explain some computing relationships as master/slave
|
||||||
|
# some people consider this outdated and harmful, so "main" is a more common these days
|
||||||
|
# also, I'll be using main, so this will help make your output look like mine
|
||||||
|
git config --global init.defaultbranch main
|
||||||
|
|
||||||
|
# this sets our information
|
||||||
|
# if we don't set this, git will prompt us to set it later
|
||||||
|
git config --global user.name <your-name>
|
||||||
|
git config --global user.email <your-email>
|
||||||
|
```
|
||||||
|
|
||||||
|
## git going
|
||||||
|
|
||||||
|
(no, that's not a real `git` command)
|
||||||
|
|
||||||
|
there's two main ways to start:
|
||||||
|
|
||||||
|
1. create a new project on our local machine, or
|
||||||
|
1. work with an existing project
|
||||||
|
|
||||||
|
> tip: `git` and associated tooling refer to projects as **repositories**. I'll be sticking with the word project here as I find it a bit friendlier, but you'll probably run across the word repository in the wider world of `git`
|
||||||
|
|
||||||
|
### git init
|
||||||
|
|
||||||
|
`git init <project>` will create a new directory named `project` ready to be used with git. We can then use `cd <project>` to enter the directory.
|
||||||
|
|
||||||
|
> tip: don't use spaces in your project name!
|
||||||
|
|
||||||
|
### git clone
|
||||||
|
|
||||||
|
`git clone <project URL>` will pull in an existing project. We're not going to talk about this right now; instead, we're going forward assuming with `git init`.
|
||||||
|
|
||||||
|
## git status
|
||||||
|
|
||||||
|
before we do anything, let's see what `git` will tell us about our project. Type `git status` and we might see the following:
|
||||||
|
|
||||||
|
```txt
|
||||||
|
On branch main
|
||||||
|
|
||||||
|
No commits yet
|
||||||
|
|
||||||
|
nothing to commit (create/copy files and use "git add" to track)
|
||||||
|
```
|
||||||
|
|
||||||
|
let's dissect this.
|
||||||
|
|
||||||
|
### branch main
|
||||||
|
|
||||||
|
`git` has a concept of **branches**, which are different paths our file history has taken. While branches are *incredibly* powerful, we're going to stay away from branches during this walkthrough and focus on working on a single branch - in this case, `main`.
|
||||||
|
|
||||||
|
### no commits / nothing to commit
|
||||||
|
|
||||||
|
"no commits" means that the project has no history whatsoever. "Nothing to commit" means we've made no changes. But what is a commit?
|
||||||
|
|
||||||
|
## commits and history
|
||||||
|
|
||||||
|
a **commit** is one set of changes made to our work. We get to choose which changes are part of any given commit, and we write a message describing the commit so that future-us knows what we did if for some reason we need to undo something.
|
||||||
|
|
||||||
|
### git log
|
||||||
|
|
||||||
|
in an established project, we can use `git log` to look at our **commit history**. By default, one commit will output like this:
|
||||||
|
|
||||||
|
```txt
|
||||||
|
commit e2fd6c4772e61f9c074638a933eb92fc1ea885ef
|
||||||
|
Author: Lee Cattarin <lee.cattarin@gmail.com>
|
||||||
|
Date: Sun Dec 28 18:47:00 2025 -0800
|
||||||
|
|
||||||
|
fix syntax err in alt
|
||||||
|
```
|
||||||
|
|
||||||
|
In order there, we have:
|
||||||
|
|
||||||
|
1. a long string that identifies the commit
|
||||||
|
1. the author of the commit
|
||||||
|
1. the date it was created
|
||||||
|
1. the message written to describe the commit
|
||||||
|
|
||||||
|
### creating a commit
|
||||||
|
|
||||||
|
commits are made with the command `git commit`, but if we try to create a commit right now we'll be told "nothing to commit."
|
||||||
|
|
||||||
|
okay, what if we edit a file?
|
||||||
|
|
||||||
|
> tip: if you don't want to actually open your editor, just use `touch file.txt` to create a new empty file named `file.txt`
|
||||||
|
|
||||||
|
hmmm, there's still nothing to commit! What happens if we check `git status`? There's some new output!
|
||||||
|
|
||||||
|
```txt
|
||||||
|
Untracked files:
|
||||||
|
(use "git add <file>..." to include in what will be committed)
|
||||||
|
file.txt
|
||||||
|
```
|
||||||
|
|
||||||
|
`git` tells us that we have "untracked" files - a.k.a. files that git hasn't got in its history yet. It also tells us to use `git add` if we want to be able to commit that file.
|
||||||
|
|
||||||
|
## the staging area
|
||||||
|
|
||||||
|
`git` has a concept called the **staging environment** or **staging area**. This captures the set of changes we're adding to a single commit. When we add something to the staging area, we say we are **staging** it or that it is **staged**. In order to stage changes, we'll use `git add`.
|
||||||
|
|
||||||
|
why a staging area? Why not just commit our changes?
|
||||||
|
|
||||||
|
well, imagine we're writing a blog post (easy for me to imagine right now). We start reviewing it, and notice that there's a bit of page styling we don't like - not something tied to the content of the post, but the styling of the overall site. We fix it, and want to save *that* change while continuing to work on our post draft. `git add` and the staging area allow that kind of choice.
|
||||||
|
|
||||||
|
### git add
|
||||||
|
|
||||||
|
`git add <filename>` lets us add *all* changes in the given file to the staging area. Sometimes this is really useful - if we just created a new file (by, say, using `touch file.txt`), we probably want to add the whole thing.
|
||||||
|
|
||||||
|
personally, I really like using `git add -p`, so much so that I [wrote an entire blog post about it](/favorite-git-flag). It lets us review changes piece-by-piece and pick only the pieces we want.
|
||||||
|
|
||||||
|
for now, we'll try `git add file.txt`. We'll notice there's no output by default, but we can run `git status` to see where things are at. `git` will now tell us:
|
||||||
|
|
||||||
|
```txt
|
||||||
|
Changes to be committed:
|
||||||
|
(use "git rm --cached <file>..." to unstage)
|
||||||
|
new file: file.txt
|
||||||
|
```
|
||||||
|
|
||||||
|
*now* we're ready to create a commit!
|
||||||
|
|
||||||
|
## git commit
|
||||||
|
|
||||||
|
if we just write `git commit`, it'll open an editor for us to edit the **commit message** - our description of the changes. This can be handy if we want to write a lengthy description, but if we want to just write a one-liner, we can use `git commit -m "<message>"`. It's quicker and doesn't involve opening an editor.
|
||||||
|
|
||||||
|
let's create a super basic commit:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
git commit -m "baby's first commit"
|
||||||
|
```
|
||||||
|
|
||||||
|
> tip: as excited as you may be, don't use '!' in your commit messages
|
||||||
|
|
||||||
|
we'll see output like this:
|
||||||
|
|
||||||
|
```txt
|
||||||
|
[main (root-commit) 3dcf1ca] baby's first commit
|
||||||
|
1 file changed, 1 insertion(+)
|
||||||
|
```
|
||||||
|
|
||||||
|
### checking our work
|
||||||
|
|
||||||
|
trying `git log` now will show us our single commit!
|
||||||
|
|
||||||
|
> tip: type `q` to exit the `git log` output
|
||||||
|
|
||||||
|
trying `git status` will tell us:
|
||||||
|
|
||||||
|
```txt
|
||||||
|
On branch main
|
||||||
|
nothing to commit, working tree clean
|
||||||
|
```
|
||||||
|
|
||||||
|
## changes to existing files
|
||||||
|
|
||||||
|
so, we've added a new file - that wasn't bad. Things get a little more interesting when we edit files `git` already knows about. Let's use `<editor-command> .` to open the current directory and write a sentence or two in `file.txt`.
|
||||||
|
|
||||||
|
after saving `file.txt`, try `git status` again.
|
||||||
|
|
||||||
|
> tip: Ctrl+S (or Cmd+S on Mac) is the shortcut for saving *basically everywhere*
|
||||||
|
|
||||||
|
```txt
|
||||||
|
Changes not staged for commit:
|
||||||
|
(use "git add <file>..." to update what will be committed)
|
||||||
|
(use "git restore <file>..." to discard changes in working directory)
|
||||||
|
modified: file.txt
|
||||||
|
```
|
||||||
|
|
||||||
|
### git restore
|
||||||
|
|
||||||
|
`git restore` is new! That lets us get rid of our changes and go back to the last version of the file committed. Be careful with this - we should only do it if we *really* want to get rid of those changes.
|
||||||
|
|
||||||
|
let's not restore, and instead stage and commit our new changes:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
git add file.txt
|
||||||
|
git commit -m "added a new sentence"
|
||||||
|
```
|
||||||
|
|
||||||
|
again, we can use `git status` or `git log` as needed.
|
||||||
|
|
||||||
|
## git revert
|
||||||
|
|
||||||
|
ooooh... I don't actually like that change. What if I want to undo something?
|
||||||
|
|
||||||
|
run `git log` again, and copy the first 6-8 characters in the commit string (we can copy more, including the whole string if we want, but it's not necessary):
|
||||||
|
|
||||||
|
```
|
||||||
|
commit 8b5dd7838f8c8423cfa445b6cddbed88e9c32511 (HEAD -> main)
|
||||||
|
Author: Lee Cattarin <lee.cattarin@gmail.com>
|
||||||
|
Date: Wed Jan 7 15:18:45 2026 -0800
|
||||||
|
|
||||||
|
added a new sentence
|
||||||
|
```
|
||||||
|
|
||||||
|
in this case, `8b5dd7`.
|
||||||
|
|
||||||
|
now we can try `git revert <commit-string>`. It'll open our editor to write a message about the change. It's important to know that `git revert` *doesn't delete the old commit* - it creates a **new** commit that undoes the previous work.
|
||||||
|
|
||||||
|
```txt
|
||||||
|
[main 9268d5c] Revert "added a new sentence"
|
||||||
|
1 file changed, 1 deletion(-)
|
||||||
|
```
|
||||||
|
|
||||||
|
I didn't edit the message - we can tell because it just says "Revert" and then the old commit message. But we can edit and add lots of detail about why we're doing it.
|
||||||
|
|
||||||
|
## git remote
|
||||||
|
|
||||||
|
let's try a new command: `git remote`. Hmm, nothing happened... what's a "remote"?
|
||||||
|
|
||||||
|
remember how I said we could use `git clone` to work on an existing project? If we did that, we'd be getting that project from a *remote* server - not our *local* machine.
|
||||||
|
|
||||||
|
the world of git servers is vast - hell, you can run your own! - but we're going to just mention a few major hosts: GitHub, GitLab, and Codeberg. For this walkthrough, we're going to work with Codeberg, but you'll find that the UI is pretty similar across all three, so if you've got a GitHub or GitLab account feel free to use that.
|
||||||
|
|
||||||
|
let's head on over to [Codeberg](https://codeberg.org/){target="_blank" rel="external"} First off, we'll make an account.
|
||||||
|
|
||||||
|
now we'll make a new project using the `+` in the upper right. Choose 'New repository,' then pick a repository name. You can leave the other settings be.
|
||||||
|
|
||||||
|
with the project created, Codeberg will tell us three things we can do: clone the repository, create a new repository, or push an existing repository. We'll push an existing one.
|
||||||
|
|
||||||
|
```sh
|
||||||
|
git remote add origin https://codeberg.org/inherentlee/testing.git
|
||||||
|
git push -u origin main
|
||||||
|
```
|
||||||
|
|
||||||
|
first, we'll add a remote. Across from the project title, we should see a button that says `Code` with a dropdown indicator. It'll offer a few choices, the first two being SSH and HTTPS. I'll talk about SSH in a bit, but let's try HTTPS first. Copy that URL; we're about to use it in a command.
|
||||||
|
|
||||||
|
> tip: the remote can be named whatever you want! Traditionally, it's called `origin`, but if it's easier for you to remember, you might call it `codeberg` or maybe `remote`
|
||||||
|
|
||||||
|
```sh
|
||||||
|
git remote add <remote-name> <url>
|
||||||
|
```
|
||||||
|
for this walkthrough, we'll call our remote `codeberg`.
|
||||||
|
|
||||||
|
there's no feedback, but that's ok. Re-running `git remote` shows that we have a remote now: `codeberg`. That really doesn't tell us much, does it! Let's try a more talkative command: `git remote --verbose` or, more simply, `git remote -v`. Now it tells us the following:
|
||||||
|
|
||||||
|
```txt
|
||||||
|
codeberg https://codeberg.org/inherentlee/git-intro.git (fetch)
|
||||||
|
codeberg https://codeberg.org/inherentlee/git-intro.git (push)
|
||||||
|
```
|
||||||
|
|
||||||
|
cool! we have a remote set up. What does "fetch" and "push" mean?
|
||||||
|
|
||||||
|
### git fetch (and git pull)
|
||||||
|
|
||||||
|
`git fetch` brings **remote** changes to our local machine. So does a command called `git pull`. Why are there two?
|
||||||
|
|
||||||
|
`fetch` brings the remote changes down, but *doesn't combine them yet with our local work*. This gives us a chance to explore what those changes are before we actually integrate them into our work!
|
||||||
|
|
||||||
|
this may seem unhelpful if we're thinking about this project as something only we work on, but imagine there's a team of people all contributing to the project. What if we *and* another person both work on the same file? Our changes might overlap!
|
||||||
|
|
||||||
|
if we're working alone and *from one machine*, we'll pretty much never have to use `git fetch` or `git pull`! If we happen to do our work on multiple machines - for example, I do some work on my PC and some on my fruitpad (using an app called [Working Copy](https://workingcopy.app/){target="_blank" rel="external"}) - we'll probably update the remote from one machine, then need to pull that work down onto the other machine.
|
||||||
|
|
||||||
|
for our use case, we can pretty safely stick to `git pull` (if we ever even need to use it!), but if you're working in a larger collaborative project, `git fetch` is your friend!
|
||||||
|
|
||||||
|
### git push, take one
|
||||||
|
|
||||||
|
`git push` is the opposite of `git pull` - it takes your local changes and adds them to the remote.
|
||||||
|
|
||||||
|
the first time we use it on any given branch, we'll want to set what's called the **upstream** - the remote branch that our local branch is connected to by default. We can do this with the following command:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
git push --set-upstream codeberg main
|
||||||
|
# or, for brevity
|
||||||
|
git push -u codeberg main
|
||||||
|
```
|
||||||
|
|
||||||
|
### authentication
|
||||||
|
|
||||||
|
when we call `git push`, we're prompted for our Codeberg username and password.
|
||||||
|
|
||||||
|
personally, I find constantly authenticating tremendously annoying! There's a couple of ways to handle this.
|
||||||
|
|
||||||
|
1. in the command line, we can use a few different credential management settings:
|
||||||
|
- `git config --global credential.helper cache` will store our username and password in memory. You'll be re-prompted every 15 minutes. I work in long enough sessions that this is still a pain for me, but it may work for you
|
||||||
|
- `git config --global credential.helper store` will save our username and password in a file on our machine, and only re-prompt if we change either value. **Importantly,** this method does *not* encrypt our password in any way! While it's convenient, it's not very secure
|
||||||
|
- on Mac, `git config --global credential.helper osxkeychain` is a secure method for saving credentials
|
||||||
|
1. if we installed `git` for Windows, we should have Git Credential Manager (GCM)
|
||||||
|
1. in *any* terminal environment, we can use an SSH key. This is my preferred method! I find it's a good balance between *never* logging in and *constantly* logging in - I do it once after opening the terminal, and them I'm good for that work session
|
||||||
|
|
||||||
|
### SSH keys
|
||||||
|
|
||||||
|
while I'm not going to go into a lot of the technical concepts behind SSH keys, I will talk a bit about how my setup works. If you're happy with one of the other credential management setups above, feel free to [skip past this section](#git-push-take-two) cause it's a bit chunky.
|
||||||
|
|
||||||
|
the SSH (secure shell) protocol allows for secure communication on an insecure network.
|
||||||
|
|
||||||
|
when we generate an SSH key, we get a **public** and a **private** key. These are mathematically related, and if we *encrypt* something with the private key, it can be *decrypted* with the public key, and vice versa.
|
||||||
|
|
||||||
|
the important thing to know is *you should never share your private key*. Also, while you aren't *forced* to set a password when creating these keys, I strongly recommend doing so.
|
||||||
|
|
||||||
|
#### creation
|
||||||
|
|
||||||
|
running `ssh-keygen` will take us through a series of prompts. Assuming we don't already have an SSH key, the default file location is fine.
|
||||||
|
|
||||||
|
when you choose a passphrase, *write it down*. If you lose it, there is no recourse. You will have to generate a new SSH key.
|
||||||
|
|
||||||
|
after generation, we will have two files at the location specified by the tool (or the custom location we chose). Generally, that's the folder `.ssh` in our home directory. If we navigate to that directory (`cd $HOME/.ssh`) and look at the files (`ls`), we'll see files named `id_rsa` and `id_rsa.pub`. The one that ends with `.pub` is the *public* key.
|
||||||
|
|
||||||
|
#### an alias...
|
||||||
|
|
||||||
|
time for a little more terminal knowledge!
|
||||||
|
|
||||||
|
I have two handy pieces of tooling in my terminal that I use for SSH operations.
|
||||||
|
|
||||||
|
the first one is an *alias* - basically a simple shortcut for a command. I've written an alias for outputting my public key so that when I need it, I can get it without having to write out the path to the key. Laziness is a virtue, okay?
|
||||||
|
|
||||||
|
there's a file in the home directory called `.bashrc`. It sets a lot of terminal-wide functionality. We're going to add an alias to it!
|
||||||
|
|
||||||
|
the command to output a file's contents is `cat <filename>`. My alias name of choice to `cat` my public SSH key is `sshcat` - but feel free to name yours something else.
|
||||||
|
|
||||||
|
navigate to the home directory (`cd`) and open your `.bashrc` file in your editor (`<editor-command> .bashrc`). Add the following to the bottom before saving and exiting.
|
||||||
|
|
||||||
|
```txt
|
||||||
|
alias sshcat="cat $HOME/.ssh/id_rsa.pub"
|
||||||
|
```
|
||||||
|
|
||||||
|
> tip: don't be alarmed if you can't use this right away! Your `.bashrc` file takes effect when the terminal starts up. If you want to test it, either restart your terminal, or type `source $HOME/.bashrc`
|
||||||
|
|
||||||
|
#### and a function
|
||||||
|
|
||||||
|
the other piece of shortcut SSH key tooling I use is a *function* that I call `ssa`, short for `ssh-agent`. `ssh-agent` manages SSH keys and keeps us logged in during a session.
|
||||||
|
|
||||||
|
```sh
|
||||||
|
# SSH agent
|
||||||
|
ssa() {
|
||||||
|
ssa_pid=$(pgrep ssh-agent)
|
||||||
|
if [[ $ssa_pid ]]; then kill $ssa_pid; fi
|
||||||
|
|
||||||
|
echo -n "$fg[green]"
|
||||||
|
eval $(ssh-agent -s)
|
||||||
|
ssh-add ~/.ssh/id_rsa
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
look, I'll be honest... we're not going to explain this one in detail. In short, though, it removes any existing instance of `ssh-agent`, then prompts us to put in our SSH key password so it can authenticate us.
|
||||||
|
|
||||||
|
open the `.bashrc` file again for editing, and add the above function to the bottom before saving and exiting. Again, either quit the terminal or type `source $HOME/.bashrc` to reload and use this new function by typing in `ssa`.
|
||||||
|
|
||||||
|
#### SSH keys and the remote
|
||||||
|
|
||||||
|
when we [added a remote](#git-remote), we used the HTTPS URL. Let's update to using the SSH URL - you can find this on the main project page under the dropdown button that reads `Code`.
|
||||||
|
|
||||||
|
```sh
|
||||||
|
git remote set-url codeberg <new-url>
|
||||||
|
```
|
||||||
|
|
||||||
|
we'll notice that the SSH URL starts with `git@`, whereas the HTTPS URL started with `https://`.
|
||||||
|
|
||||||
|
in order for all this to be useful, we need to tell Codeberg about our SSH key. In Codeberg, navigate to [settings, then find the left-hand tab for SSH keys](https://codeberg.org/user/settings/keys){target="_blank" rel="external"}. Choose 'Add key' and paste in the **public** key (if you set up that `sshcat` alias, use it now to output your key for ease of copying). Save and we'll now be set up to authenticate with SSH!
|
||||||
|
|
||||||
|
### git push, take two
|
||||||
|
|
||||||
|
we can now call `git push` again and again now without having to repeat our credentials every time. We can also call `git pull` for our private repositories.
|
||||||
|
|
||||||
|
## summary
|
||||||
|
|
||||||
|
let's talk about what we've done.
|
||||||
|
|
||||||
|
1. set up a terminal and learned a couple indispensable commands
|
||||||
|
1. created a new project with `git init`
|
||||||
|
1. checked in *constantly* using `git status`
|
||||||
|
1. learned what a commit is, and how to use `git log` to view our commit history
|
||||||
|
1. used `git add` to add new files or file changes to a commit
|
||||||
|
1. created commits with `git commit`
|
||||||
|
1. undid a commit using `git revert`
|
||||||
|
1. talked about remotes, making a new Codeberg project, and using `git remote` to link that project to our local work
|
||||||
|
1. talked about `git fetch` and `git pull`
|
||||||
|
1. added our local work to the remote project using `git push`
|
||||||
|
1. and finally, set up some kind of credential management so we don't have to log in for *every* `git push`!
|
||||||
|
|
||||||
|
congratulations, and welcome to `git`!
|
||||||
126
src/posts/2026/2026-01-08-comparing-text-editors.md
Normal file
@ -0,0 +1,126 @@
|
|||||||
|
---
|
||||||
|
title: comparing text editors
|
||||||
|
image:
|
||||||
|
src: 2026/horsetail.jpg
|
||||||
|
alt: "Image unrelated to post. Close up on a horsetail plant's stem, with many small needle-like leaves emerging from all sides of the circular stem at each segmented joint."
|
||||||
|
tags:
|
||||||
|
- reference
|
||||||
|
- software
|
||||||
|
---
|
||||||
|
|
||||||
|
I'm fucking depressed. No, not like mental health depressed (okay, look, that too, but that's not relevant here). Looking to switch text editors, I reviewed 6 different options...and what I found didn't thrill me.
|
||||||
|
|
||||||
|
> this post contains comparison tables that are far more viewable on desktop/tablet
|
||||||
|
|
||||||
|
## the editors
|
||||||
|
|
||||||
|
the editors I reviewed, in no particular order, are:
|
||||||
|
|
||||||
|
- [VSCode](https://code.visualstudio.com/){target="_blank" rel="external"} (my current daily driver which I've been wanting to leave behind for a while now)
|
||||||
|
- [Zed](https://zed.dev/){target="_blank" rel="external"} (an editor I've been tentatively interested in)
|
||||||
|
- [Kate](https://kate-editor.org/){target="_blank" rel="external"} (recommended to me semi-recently on the fediverse, but one I quickly wrote off at the time because of clunkiness)
|
||||||
|
- [Lapce](https://lap.dev/lapce/){target="_blank" rel="external"} (recommended via fedi)
|
||||||
|
- [Pulsar](https://pulsar-edit.dev/){target="_blank" rel="external"} (a fork of the discontinued Atom editor, recommended again by fedi, in the course of this review)
|
||||||
|
- and finally, [Sublime Text](https://www.sublimetext.com/){target="_blank" rel="external"} (my daily driver back in college)
|
||||||
|
|
||||||
|
## the qualities
|
||||||
|
|
||||||
|
I reviewed looking for 5 major **functional** qualities that I considered to be my most useful or heavily-used features:
|
||||||
|
|
||||||
|
- `.editorconfig` support
|
||||||
|
- find and replace with regex support
|
||||||
|
- WSL support (including, because apparently this is an issue, the ability to delete files from inside the editor) (this is the highest priority - I do *all* work in WSL)
|
||||||
|
- multi-edit (e.g. ability to select multiple instances of a word and edit them all) (this is the most discardable functionality, as it can be replaced with find-and-replace)
|
||||||
|
- markdown preview
|
||||||
|
|
||||||
|
3 less important, but preferred, **aesthetic** qualities:
|
||||||
|
|
||||||
|
- clean, modern UI
|
||||||
|
- file type icons
|
||||||
|
- ability to customize the color scheme (ideally per-color settings, but that's uncommon)
|
||||||
|
|
||||||
|
and finally, 3 **ethical and trustworthiness** qualities:
|
||||||
|
|
||||||
|
- no LLM features
|
||||||
|
- for products with LLM features: single setting to turn off LLM features
|
||||||
|
- trust that product longevity will not be affected by LLM-generated code
|
||||||
|
|
||||||
|
(in other words: no LLMs).
|
||||||
|
|
||||||
|
## the comparison charts
|
||||||
|
|
||||||
|
### functional qualities
|
||||||
|
|
||||||
|
| | `.editorconfig` | find-and-replace | WSL | multi-edit | `.md` preview |
|
||||||
|
|---|---|---|---|---|---|
|
||||||
|
| VSCode | **yes**[1] | **yes** | **yes**[1] | **yes** | **yes** |
|
||||||
|
| Zed | **yes**[1] | **yes** | **yes** | **yes** | **yes** |
|
||||||
|
| Kate | **yes** | **yes** | no[2] | **yes** | no |
|
||||||
|
| Lapce | no | **yes** | no[3] | **yes** | no |
|
||||||
|
| Pulsar | no | **yes** | no[3] | **yes** | **yes** |
|
||||||
|
| Sublime Text | **yes** | **yes** | no[3][4] | **yes** | no[5] |
|
||||||
|
|
||||||
|
[1] extension needed: [VSCode `.editorconfig`](https://marketplace.visualstudio.com/items?itemName=EditorConfig.EditorConfig){target="_blank" rel="external"}, [VSCode WSL](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.vscode-remote-extensionpack){:target="_blank"}, [Zed `.editorconfig`](https://zed.dev/extensions/editorconfig){:target="_blank"}
|
||||||
|
|
||||||
|
[2] I could open a WSL directory in Kate, but couldn't see any files. I confirmed that opening a Windows directory worked as expected.
|
||||||
|
|
||||||
|
[3] opening the project worked fine, but I couldn't delete files. In Sublime Text's case, they were deleted but still shown in the file view.
|
||||||
|
|
||||||
|
[4] saving a new file opens the save menu in the Windows File Explorer, which frankly makes me a bit afraid. Touching your WSL files from Windows is generally a bad idea.
|
||||||
|
|
||||||
|
[5] I explored two different add-on packages for Markdown preview support. [Markdown Live Preview](https://packagecontrol.io/packages/MarkdownLivePreview){target="_blank" rel="external"} and [MarkdownPreview](https://packagecontrol.io/packages/MarkdownPreview){:target="_blank"}. Markdown Live Preview opened a whole new window scoped only to the specific `.md` file. MarkdownPreview previewed in browser. Neither of these match the behavior I am looking for.
|
||||||
|
|
||||||
|
### aesthetic qualities
|
||||||
|
|
||||||
|
| | UI | file icons | color scheme |
|
||||||
|
|---|---|---|---|
|
||||||
|
| VSCode | **yes** | **yes** | **yes**[1] |
|
||||||
|
| Zed | **yes** | **yes** | **yes**[2] |
|
||||||
|
| Kate | no | **yes** | **yes**[2] |
|
||||||
|
| Lapce | **yes** | no | **yes**[3] |
|
||||||
|
| Pulsar | **yes** | no | **yes**[1] |
|
||||||
|
| Sublime Text | **yes** | **yes** | **yes** |
|
||||||
|
|
||||||
|
[1] several color schemes available. Further extensions available.
|
||||||
|
|
||||||
|
[2] several color schemes available.
|
||||||
|
|
||||||
|
[3] only light and dark schemes available. Further plugins available.
|
||||||
|
|
||||||
|
### ethical qualities
|
||||||
|
|
||||||
|
this is my best guess based on searching online and reviewing the settings; it's kind of hard to really confirm these things. I am judging the last quality - whether or not the devs are using LLMs - based on the existence of `prompts` directories in the projects' repositories.
|
||||||
|
|
||||||
|
| | no LLM features | LLM kill switch | no LLM code |
|
||||||
|
|---|---|---|---|
|
||||||
|
| VSCode | no | no | no[1] |
|
||||||
|
| Zed | no | **yes** | no[2] |
|
||||||
|
| Kate | **yes** | n/a | **yes** |
|
||||||
|
| Lapce | **yes** | n/a | **yes** |
|
||||||
|
| Pulsar | **yes** | n/a | **yes**[3] |
|
||||||
|
| Sublime Text | **yes** | n/a | unknown[4] |
|
||||||
|
|
||||||
|
[1] [prompts directory](https://github.com/microsoft/vscode/tree/main/.github/prompts){target="_blank" rel="external"}
|
||||||
|
|
||||||
|
[2] looks like at current LLMs are only used for [documentation](https://github.com/zed-industries/zed/tree/main/.factory/prompts){target="_blank" rel="external"}
|
||||||
|
|
||||||
|
[3] it's been discussed and sounds currently up for debate: [Pulsar](https://github.com/pulsar-edit/pulsar/issues/792){target="_blank" rel="external"}, [Sublime Text](https://forum.sublimetext.com/t/implement-ai-into-sublime-text/68411){:target="_blank"}
|
||||||
|
|
||||||
|
[4] I couldn't find the source code for Sublime Text online; I assume it's not OSS. If you know where it is, point me in that direction.
|
||||||
|
|
||||||
|
## summary
|
||||||
|
|
||||||
|
I'll be honest, I just don't know. The functionality is not something I can easily compromise on. TBH, I figured I had pretty basic needs as a developer, but it seems that's not the case! The only editors that meet my functionality needs across the board are *also* the worst offenders on the LLM front.
|
||||||
|
|
||||||
|
at the end of the day, I might just have to keep looking... but regardless, I wanted to publish what I found to help anyone else with similar needs.
|
||||||
|
|
||||||
|
## corrections and edits
|
||||||
|
|
||||||
|
- Kate *does* have multi-edit
|
||||||
|
- Lapce has plugins for further color schemes
|
||||||
|
- VSCode WSL support requires an extension
|
||||||
|
- Zed `.editorconfig` support requires an extension
|
||||||
|
|
||||||
|
### WSL2 and Linux GUIs
|
||||||
|
|
||||||
|
I learned that [WSL2 can support GUI apps](https://learn.microsoft.com/en-us/windows/wsl/tutorials/gui-apps){target="_blank" rel="external"} so I tried this for a few. Pulsar did not work; Sublime Text worked but the UI scale was *teensy* and was not affected by the `ui_scale` setting.
|
||||||
94
src/posts/2026/2026-01-11-spinning-plants.md
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
---
|
||||||
|
title: spinning plants
|
||||||
|
image:
|
||||||
|
src: 2026/plant-handspun.jpg
|
||||||
|
alt: "6 small skeins of handspun yarn, each made from a different plant fiber. from top, we have flax (medium brown, rough); what is probably lotus (golden, shiny and soft); banana (white and semi shiny); hemp (light brown, rough); tencel (white and very shiny); ramie (a particularly small skein, white and semi shiny)"
|
||||||
|
tags:
|
||||||
|
- reference
|
||||||
|
- yarn
|
||||||
|
---
|
||||||
|
|
||||||
|
> work in progress! To be updated as I continue spinning.
|
||||||
|
|
||||||
|
in picture, from top:
|
||||||
|
|
||||||
|
1. flax
|
||||||
|
1. (probably) lotus
|
||||||
|
1. banana
|
||||||
|
1. hemp
|
||||||
|
1. tencel
|
||||||
|
1. rose
|
||||||
|
1. ramie
|
||||||
|
|
||||||
|
notes on handspinning various plant fibers. Fibers were purchased as a [sample pack from Hearthside Fibers](https://www.etsy.com/listing/1141552359/plant-based-fiber-top-sampler-pack-vegan){target="_blank" rel="external"}. Unfortunately, I spun the first sample - flax - in 2023, so don't have thoughts on that left in my head. I also received a mystery sample along with the 12 named samples that *may* have been lotus - it's the smallest skein in the image. The lotus was also spun in 2023.
|
||||||
|
|
||||||
|
- overall, these are broadly more slippery than wool
|
||||||
|
- most if not all of these benefitted from pre-drafting moreso than I usually do for wool
|
||||||
|
|
||||||
|
## ease of spinning
|
||||||
|
|
||||||
|
- **easy:** flax, hemp
|
||||||
|
- **middling:** banana, tencel
|
||||||
|
- **hard:** rose
|
||||||
|
- **worst:** ramie
|
||||||
|
|
||||||
|
## texture (of final yarn)
|
||||||
|
|
||||||
|
- **softest:** rose
|
||||||
|
- **pleasant:** banana, tencel
|
||||||
|
- **meh:** ramie
|
||||||
|
- **itchy:** hemp, flax
|
||||||
|
|
||||||
|
## density/thickness
|
||||||
|
|
||||||
|
I am estimating this via yards per gram of fiber. Other than the flax and lotus (can't promise anything there), I aimed for my average spin with all of these and spun them on the same tool (Wheeliam, an Ashford Kiwi 3). Per-fiber notes mention whether they spun thick or thin if notable.
|
||||||
|
|
||||||
|
| fiber | yards | grams | yds/g |
|
||||||
|
|---|---|---|---|
|
||||||
|
| banana | 33 | 22 | 1.50 |
|
||||||
|
| flax | 33 | 27 | 1.22 |
|
||||||
|
| hemp | 41 | 26 | 1.58 |
|
||||||
|
| lotus | 16 | 12 | 1.33 |
|
||||||
|
| rose | 60 | 29 | 2.07 |
|
||||||
|
| tencel | 31 | 29 | 1.07 |
|
||||||
|
| ramie | 7.5 | 5 | 1.5 |
|
||||||
|
|
||||||
|
## per-fiber breakdown
|
||||||
|
|
||||||
|
written up in order of spinning.
|
||||||
|
|
||||||
|
### banana
|
||||||
|
|
||||||
|
- felt a bit wear-y on the hands - that may have been the silk I spun earlier that day though
|
||||||
|
- a bit hard to draft, quite liked to stick to itself and clump, but once moving was *quite* slippery
|
||||||
|
|
||||||
|
### hemp
|
||||||
|
|
||||||
|
- awful feeling. awful awful awful. hate.
|
||||||
|
- easy to spin
|
||||||
|
- quite grippy
|
||||||
|
- easy joins
|
||||||
|
- difficult to tell apart from stray plant matter
|
||||||
|
|
||||||
|
### rose
|
||||||
|
|
||||||
|
- incredibly soft; shiny and very pretty
|
||||||
|
- quite difficult to spin
|
||||||
|
- wanted to spin thin
|
||||||
|
- joins were tough, it's quite slippery
|
||||||
|
- needed slow and careful drafting because of the above - I brought my wheel down to a lower ratio which is rare
|
||||||
|
|
||||||
|
### tencel
|
||||||
|
|
||||||
|
- also felt a bit wear-y like banana
|
||||||
|
- spun a bit thick and liked to clump
|
||||||
|
- not as bad as rose on the slippery front
|
||||||
|
- very shiny, almost glittery in spots
|
||||||
|
- dense and spun up fast
|
||||||
|
|
||||||
|
### ramie
|
||||||
|
|
||||||
|
- hated this
|
||||||
|
- slippery af
|
||||||
|
- **constantly** splitting all over the place so I couldn't keep the fibers aligned in the slightest
|
||||||
|
- stopped after 5g because it sucked and I didn't care to finish it
|
||||||
11
src/posts/2026/2026-01-18-bfl-silk-handspun.md
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
---
|
||||||
|
title: BFL/silk handspun
|
||||||
|
image:
|
||||||
|
src: 2026/bfl-silk-handspun.jpg
|
||||||
|
alt: "a spinning wheel bobbin full of undyed white handspun yarn in about a sport or DK weight."
|
||||||
|
tags:
|
||||||
|
- gallery
|
||||||
|
- yarn
|
||||||
|
---
|
||||||
|
|
||||||
|
Fiber from [Woolgatherings](https://woolgatherings.com){target="_blank" rel="external"}. 70% Blue-Faced Leicester 30% tussah silk.
|
||||||
11
src/posts/2026/2026-01-18-coral-reef-handspun.md
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
---
|
||||||
|
title: coral reef handspun
|
||||||
|
image:
|
||||||
|
src: 2026/coral-reef-handspun.jpg
|
||||||
|
alt: "2 skeins, one large and one small, of a heathered grey yarn with hints of blue and orange in about a sport or DK weight."
|
||||||
|
tags:
|
||||||
|
- gallery
|
||||||
|
- yarn
|
||||||
|
---
|
||||||
|
|
||||||
|
Fiber from [Jakira Farms](https://www.etsy.com/shop/JakiraFarms){target="_blank" rel="external"} in Coral Reef colorway. 100% merino.
|
||||||
11
src/posts/2026/2026-01-18-dyeing-fiber.md
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
---
|
||||||
|
title: dyeing fiber
|
||||||
|
image:
|
||||||
|
src: 2026/dyed-fiber.jpg
|
||||||
|
alt: "4oz of yarn and a pound of wool, chunked out, drying on a drying rack outdoors. the yarn and half the wool is a mix of teals and greens; the other half of the wool is a beautiful orange-gold."
|
||||||
|
tags:
|
||||||
|
- gallery
|
||||||
|
- yarn
|
||||||
|
---
|
||||||
|
|
||||||
|
hand-dyed with acid dyes
|
||||||
11
src/posts/2026/2026-01-18-fire-ice-handspun.md
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
---
|
||||||
|
title: fire & ice handspun
|
||||||
|
image:
|
||||||
|
src: 2026/fire-ice-handspun.jpg
|
||||||
|
alt: "2 skeins, one large and one small, of a heathered orange yarn with hints of blue in about a DK or worsted weight."
|
||||||
|
tags:
|
||||||
|
- gallery
|
||||||
|
- yarn
|
||||||
|
---
|
||||||
|
|
||||||
|
Fiber from [Jakira Farms](https://www.etsy.com/shop/JakiraFarms){target="_blank" rel="external"} in Fire & Ice colorway. 100% merino.
|
||||||
11
src/posts/2026/2026-01-18-rambouillet-handspun.md
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
---
|
||||||
|
title: rambouillet handspun
|
||||||
|
image:
|
||||||
|
src: 2026/rambouillet-handspun.jpg
|
||||||
|
alt: "1 large and 2 small skeins of handspun yarn in a sport or DK weight that has been dyed in light and dark teal, green, and rusty green-gold."
|
||||||
|
tags:
|
||||||
|
- gallery
|
||||||
|
- yarn
|
||||||
|
---
|
||||||
|
|
||||||
|
Fiber from [Woolgatherings](https://woolgatherings.com){target="_blank" rel="external"}. 100% rambouillet. Hand-dyed!
|
||||||
11
src/posts/2026/2026-01-18-spinners-dream-handspun.md
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
---
|
||||||
|
title: spinner's dream handspun
|
||||||
|
image:
|
||||||
|
src: 2026/spinners-dream-handspun.jpg
|
||||||
|
alt: "a skein of a lightly variegated grey yarn in about a sport or DK weight."
|
||||||
|
tags:
|
||||||
|
- gallery
|
||||||
|
- yarn
|
||||||
|
---
|
||||||
|
|
||||||
|
Fiber from [Paradise Fibers](https://paradisefibers.com){target="_blank" rel="external"}. 40% merino/20% alpaca/20% camel/20% mulberry silk. Scrumptiously soft.
|
||||||
11
src/posts/2026/2026-01-24-gold-handspun.md
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
---
|
||||||
|
title: hand-dyed gold handspun
|
||||||
|
image:
|
||||||
|
src: 2026/gold-handspun.jpg
|
||||||
|
alt: "3 skeins, one small and two large, of a rich golden-orange handspun with light tonal effects, in about a DK weight"
|
||||||
|
tags:
|
||||||
|
- gallery
|
||||||
|
- yarn
|
||||||
|
---
|
||||||
|
|
||||||
|
Fiber from [Paradise Fibers](https://paradisefibers.com){target="_blank" rel="external"}. 70% merino/30% nylon. Hand-dyed by me.
|
||||||
11
src/posts/2026/2026-01-27-ruby-alpaca-handspun.md
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
---
|
||||||
|
title: ruby the alpaca handspun
|
||||||
|
image:
|
||||||
|
src: 2026/ruby-alpaca-handspun.jpg
|
||||||
|
alt: "one large skein and two smaller skeins of a rich chocolatey brown alpaca handspun, in about a DK weight"
|
||||||
|
tags:
|
||||||
|
- gallery
|
||||||
|
- yarn
|
||||||
|
---
|
||||||
|
|
||||||
|
Fiber from Circle R Ranch. 100% alpaca, from Ruby the alpaca.
|
||||||
11
src/posts/2026/2026-02-05-charlie-alpaca-handspun.md
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
---
|
||||||
|
title: charlie the alpaca handspun
|
||||||
|
image:
|
||||||
|
src: 2026/charlie-alpaca-handspun.jpg
|
||||||
|
alt: "one large skein (and technically a smaller skein hidden behind it) of sheen-y black alpaca handspun, in about a DK weight"
|
||||||
|
tags:
|
||||||
|
- gallery
|
||||||
|
- yarn
|
||||||
|
---
|
||||||
|
|
||||||
|
Fiber from Circle R Ranch. 100% alpaca, from Charlie the alpaca.
|
||||||
9
src/posts/2026/2026-02-09-crow.md
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
---
|
||||||
|
title: crow
|
||||||
|
image:
|
||||||
|
src: 2026/crow-print.jpg
|
||||||
|
alt: "a block print in dark indigo ink on white paper depicting a perched crow looking over one shoulder. one side of the crow is lit with fine feather detail, and the other side is almost entirely in shadow."
|
||||||
|
tags:
|
||||||
|
- gallery
|
||||||
|
- print
|
||||||
|
---
|
||||||
98
src/posts/2026/2026-2-06-screen-reader-optimizations.md
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
---
|
||||||
|
title: screen reader optimizations
|
||||||
|
image:
|
||||||
|
src: 2026/crow.jpg
|
||||||
|
alt: "Image unrelated to post. A crow poses on driftwood against a whitish sky."
|
||||||
|
tags:
|
||||||
|
- reference
|
||||||
|
- software
|
||||||
|
---
|
||||||
|
|
||||||
|
## context
|
||||||
|
|
||||||
|
recently, I've been working on a [website for a project called spoonfairies](https://inherentlee.codeberg.page/spoonfairies/){target="_blank" rel="external"}. On the providers page, we list a series of names along with their pronouns, location, and services offered. Visually, it looks like this:
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## pronouns
|
||||||
|
|
||||||
|
at first, all three pieces of information in the top row had no extra styling - it was just a line of text with the same color and size throughout. The location bit also didn't exist yet, so we're going to briefly ignore it. Screenreader testing (with NVDA, specifically) informed me that, when reading through a long list of providers, parentheses become *very* irritating. Imagine hearing the following:
|
||||||
|
|
||||||
|
> Lorem Ipsum left parentheses she slash her right parentheses web accessiblity webdev. Dolor Sit left parentheses they slash them right parentheses housecleaning. Amet Consectetur left parentheses he slash him right parentheses webdev spreadsheets software.
|
||||||
|
|
||||||
|
...ad nauseam. Kinda irritating.
|
||||||
|
|
||||||
|
### the fix
|
||||||
|
|
||||||
|
put the pronouns in a span that provides special styling, and use `::before` and `::after` to apply parentheses.
|
||||||
|
|
||||||
|
```html
|
||||||
|
<a href="/providers/lorem-ipsum">
|
||||||
|
Lorem Ipsum
|
||||||
|
<span class="pronouns">she/her</span>
|
||||||
|
</a>
|
||||||
|
```
|
||||||
|
|
||||||
|
```css
|
||||||
|
.pronouns::before {
|
||||||
|
content: "(" / "";
|
||||||
|
}
|
||||||
|
.pronouns::after {
|
||||||
|
content: ")" / "";
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**the slash is the magic there.** The string before the slash indicates the visual content, and the string after the slash is the alternative text content. I went happily on my way.
|
||||||
|
|
||||||
|
plus, this is neat - now I can style the pronouns separately. Let's make them the standard text color rather than the link color, and a bit smaller, and a smidge opaque... nice.
|
||||||
|
|
||||||
|
## location
|
||||||
|
|
||||||
|
ooh, time to implement locations! I did my same ol' trick.
|
||||||
|
|
||||||
|
```html
|
||||||
|
<a href="/providers/lorem-ipsum">
|
||||||
|
Lorem Ipsum
|
||||||
|
<span class="pronouns">she/her</span>
|
||||||
|
<span class="location">Tacoma</span>
|
||||||
|
</a>
|
||||||
|
```
|
||||||
|
|
||||||
|
```css
|
||||||
|
.location::before {
|
||||||
|
content: "📍" / "is based out of";
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
I even added actual alternative text rather than an empty string to provide some context. Pronouns, I figured, could exist without much context, as it's pretty common for them to follow directly after names in introductions, but location isn't as much of a given.
|
||||||
|
|
||||||
|
again, style em up nice, more of a standard text look, right-aligned. Cool.
|
||||||
|
|
||||||
|
## a bigger problem than parentheses
|
||||||
|
|
||||||
|
...then I did some screen reader testing. Which I should have done directly after the pronouns bit. Turns out, I wasn't thrilled with what the `<span>`s did.
|
||||||
|
|
||||||
|
at least with fairly default settings in NVDA, the `<span>`s broke up the way the link was read out. Suddenly, I was getting:
|
||||||
|
|
||||||
|
> visited link Lorem Ipsum visited link she slash her visited link Tacoma
|
||||||
|
|
||||||
|
this is all one link, mind you. The `<a>` tag isn't broken into three links. But the `<span>`s apparently break up the screen reader output anyway (in NVDA, that's a continual caveat).
|
||||||
|
|
||||||
|
ooookay... what next?
|
||||||
|
|
||||||
|
### total overhaul
|
||||||
|
|
||||||
|
I moved away from my `content` approach entirely (well, I kept it around as a failsafe, but it's not running the show now). Instead, I switched over to an `aria-label` for the whole link.
|
||||||
|
|
||||||
|
```html
|
||||||
|
<a href="/providers/lorem-ipsum"
|
||||||
|
aria-label="Lorem Ipsum she/her is based out of Tacoma">
|
||||||
|
Lorem Ipsum
|
||||||
|
<span class="pronouns">she/her</span>
|
||||||
|
<span class="location">Tacoma</span>
|
||||||
|
</a>
|
||||||
|
```
|
||||||
|
|
||||||
|
(technically, all this is templated to hell and back. I would hope that's obvious given I'm talking about *lists* of these entries.)
|
||||||
|
|
||||||
|
now, after more screen reader testing, it reads out smoothly. The `aria-label` precludes the actual link text and cleanly says what needs to be said, with nothing breaking up the text and the whole thing easily recognized as one link. *And* I've got my fancy styling. Sweet.
|
||||||