`git unstage` as a service

59 stars
3 forks

git unstage as a service

A Git plugin for the shell that automagically remembers all the different commands there are to remove files from staging and when to use each


There are at least nine ways to unstage files in a Git repository. Remembering which versions of Git support which syntax, under which circumstances, reduced my productivity enough to publish this software in response.

This is a command-line shell plugin for undoing git add. Too many staged files? Can’t remember if it’s git reset HEAD or git restore --staged --? Just remember gunstage or git unstage.

gunstage works exactly as you would expect it to as it performs the opposite of git add. You can unstage directories and specific files in as few commands as you’d like: gunstage file1.txt file2.txt directory/.

Want to unstage everything? Well that’s as easy as gunstage --all or gunstage -A.


There is no git unstage command packaged as part of Git’s default tooling. While git restore --staged often performs the task, it’s not an obvious formula based on Git’s other commands. git restore --staged is also unreliable, having entered Git’s vocabulary in 2019, after some 14 years of releases without it. Many older releases remain in the wild and git restore causes them to fail and choke. This software gracefully and silently accounts for those situations by always sending the syntax that Git used from 2005 until 2019: git reset.

Instead of keeping up with the latest incarnation of Git, whose manual says git restore “IS EXPERIMENTAL” and “THE BEHAVIOR MAY CHANGE” (emphasis in original), you can let this script do the remembering for you.

Minutiæ of the pedantic and querulous variety

To unstage content in a Git repository â€“ that is, to undo a git add â€“ you must remember which commands are still in use out of the many I’m aware of having been recommended so far:

  1. git restore --staged (source),

  2. git reset HEAD (source),

  3. git reset -q HEAD -- (source (via))

  4. git reset (source),

  5. git restore --staged -- (source),

  6. git reset HEAD -- (source),

  7. git rm --cached (source),

  8. git reset -- (source), and even

  9. git rm --cached -- # ffs (source).

Next, you must be aware of repository context: if the repository is new and no commit has occurred yet, then git restore --staged won’t work, but gunstage will.


gunstage # 🔫 git unstage as a service
git unstage # 🔫 it just works!

Its name is an abbreviation and portmanteau of git unstage arising by analog from Oh My Zsh’s other Git aliases.


The scripts are written in Bourne shell-flavored, KornShell- and Zsh-compatible Bash, which is masquerading as Z shell with a .zsh filename extension so Oh My Zsh recognizes it as a plugin. What does that mean? The syntax is as low-tech as possible while performing sophisticated work to do one thing and do it well: git unstage.



I tested gunstage atop Zsh 5.8 and Bash 3.2 using Git:

  • 2.17 on Ubuntu 18.04,

  • 2.20 on Debian 9.12,

  • 2.28, 2.29, and 2.30 on macOS 11.0 and Alpine 3.11 and 3.12, and

From macOS, I use iTerm2; from iOS, I use iSH.


This repository’s preview image was created by Twitter.