هلالtonight’s moonشمسةthe sixteen-petal rosette — how it is drawn

The observatory

Tonight’s moonهلال

Next new moon
Next full moon

The first thin crescent — هلال, the hilal — is the moon a day or two out of conjunction, and it is a beginning. The Hijri calendar is lunar: twelve months of twenty-nine or thirty days, a year some eleven days shorter than the solar one, so its months walk backwards through the seasons. A month opens when the new crescent is seen — and the naked-eye hilal is a hard object, thin and low and lost in the dusk it hangs in, which is why what counts as seeing it has been argued over for centuries.

That is one reason the astronomers of the medieval Islamic world measured the moon as closely as they did. Al-Battani, who spent most of his life at Raqqa and died in 929, left the earliest surviving zīj — a book of astronomical tables — in the Ptolemaic tradition, and tables like it could place the crescent before anyone went out to look for it. The disc above is worked the same way: everything on it follows from ψ, the angle between sun and moon, which fixes both the phase and the lit fraction, (1 − cos ψ) ⁄ 2.

The observatory

The sixteen-petal rosetteشمسة

the compass circle · sixteen points

Everything here is stepped off one circle. Sixteen points around it, each joined to the sixth from it; the {16/6} star polygon that follows then supplies its own measurements — the petal valleys at 0.689 R where consecutive chords meet, the ring at 0.390 R where they cross closest to the centre. Nothing is chosen by eye.

Patterns built on that kind of scaffolding are girih, the interlaced strapwork behind much of Islamic geometric ornament; cut from glazed terracotta and set piece by hand-chiselled piece, the same figures become zellij, the mosaic of Morocco and al-Andalus this page is named for. What craftsmen carried between sites was the construction rather than the finished design: the Topkapı Scroll, 114 patterns from the Timurid workshops, is the one pattern-book of its kind to survive. The eight-pointed star this rosette closes on is the khatam — two squares laid across each other, the octagram the Qur’an uses in its margins as the Rub el Hizb.

Ahmed El Gabri

أحمد الجابري

Two-centred drop arch — the Mosque of Ibn Tulun, Cairo, 876–879

Blog

Introducing git-wt: Worktrees Simplified

LogoLogo

In my previous post, I explained why the bare repo pattern makes git worktrees actually pleasant to use. But setting it up manually requires 10+ commands. And the day-to-day friction - upstream tracking, orphaned branches, missing fetches - adds up.

So I built git-wt to handle the tedious parts.

How custom git commands work: Any executable named git-<cmd> in your $PATH becomes git cmd. Git’s own commands work this way - run ls $(git --exec-path) to see them all.

The Problem with Native Worktrees

Even with the bare repo pattern, native git worktree has friction:

No upstream tracking. Create a worktree from origin/feature, your first push fails with “no upstream configured.” Every single time.

Orphaned branches. Remove a worktree, the local branch stays. Six months later, git branch scrolls for pages.

Manual fetching. Forget to fetch before creating a worktree? You’re working with stale refs.

Setup dance. Want the bare repo structure? Memorize 10 commands or dig through notes.

What git-wt Does

Command What it does
clone Sets up bare structure automatically
migrate Converts existing repos (preserves all your work)
add Creates worktrees with auto-fetch and upstream
remove Removes worktree AND cleans up the local branch
destroy Nuclear: worktree + local branch + remote branch
update Fetches everything, fast-forwards default branch
switch Interactive picker (fzf) to jump between worktrees

Everything else passes through to git worktree - list, prune, lock all work.

Clone with Structure

git wt clone https://github.com/user/repo.git

That’s it. Three things in your folder: .bare/, .git, and a main/ worktree. Compare to the 10 manual commands from the previous post.

The result:

my-project/
├── .bare/            # all git data lives here
├── .git              # pointer file
└── main/             # worktree: main branch

Add a Worktree (Interactive Mode)

git wt add

Fetches first. Shows branches in fzf with a commit preview pane. Pick the branch, worktree created, upstream configured. Done.

Add a Worktree (Direct Mode)

git wt add feature-auth origin/feature-auth # existing branch
git wt add -b my-feature my-feature         # new branch

Both modes auto-configure upstream tracking. Your first push just works.

Clean Up Properly

git wt remove feature-payments

Removes the worktree directory AND deletes the local branch. No more orphans.

Go Nuclear

git wt destroy old-experiment

Removes worktree, local branch, AND remote branch. Shows you exactly what will be deleted. Requires typing the branch name to confirm - no accidental destruction.

Migrate Existing Repos

⚠️ Experimental: This command restructures your repository. It has worked on repos I’ve tested, but as a destructive action, proceed with caution until more users have validated it.

Already have a repo cloned the normal way?

cd my-repo
git wt migrate

Converts your existing clone to the bare structure. Preserves all your branches, stashes, and history. Your current working directory becomes a worktree.

Update Everything

git wt update

Fetches all remotes, fast-forwards the default branch (main/master) if possible. Run this periodically to keep your worktrees current.

Switch Between Worktrees

git wt switch

Interactive fzf picker showing all worktrees. Select one and it prints the path. Pair with cd $(git wt switch) or bind to a shell function.

you can add this to your .bashrc or .zshrc:

# Jump to a worktree
wt() {
	local dir
	dir=$(git wt switch)
	[[ -n "$dir" ]] && cd "$dir"
}

Now wt gives you an interactive picker that drops you into the selected worktree.

Installation

Homebrew

brew tap ahmedelgabri/git-wt
brew install git-wt

Nix

nix run github:ahmedelgabri/git-wt

Or add to your flake:

{
  inputs.git-wt.url = "github:ahmedelgabri/git-wt";
}

Then use inputs.git-wt.packages.${system}.default.

Manual

Copy the git-wt script somewhere in your $PATH. It’s a single bash file with no dependencies beyond git and standard unix tools (fzf for interactive mode).

Shell Completion

Includes completions for zsh, bash, and fish. (installed automatically with Homebrew and Nix)

Why a Wrapper?

The bare repo pattern is powerful but has sharp edges. git-wt smooths them:

  • Correct setup by default: clone and migrate handle all the config
  • Upstream tracking: add sets it up automatically
  • Clean deletion: remove and destroy prevent orphans
  • Discoverability: Commands match mental model (“add a worktree”, not “add a worktree and also set upstream and also remember to fetch first”)

The goal is making worktrees feel as natural as git checkout - but with full isolation.

Try It

# New project
git wt clone https://github.com/some/repo.git
cd repo/main

# Existing project
cd existing-repo
git wt migrate

Work like this for a week. The friction disappears.


Links:

You can share this post or reach me on @ahmedelgabri.