Git Add All Except Some
At my current day job, every now and then I need to toggle some feature flags which we have in tracked env files. So I always wish I had a single git command to add all the files except that one, when I still need it locally but want to commit. Something like git stop <file>
that will stage everything excluding the given files.
I’m sure there are other use cases besides the very niche one I’ve just given. I personally encounter this need occasionally so I’ve done a quick search, and business as usual with git, there’s plenty of ways to do it. But nothing close to a single and simple command.
You either have to undo something later like when you need to reset the file after adding all:
git add .
git reset -- path/to/file.js
Or use the :!
pathspec (short for :(exclude)
) to exclude the files:
git add --all -- ':!path/to/file1.js' ':!path/to/file2.js' ':!path/to/folder/*'
but will have to spell it letter by letter because the CLI autocomplete gets confused by the additional characters before the file paths. Certainly cumbersome for someone who refuses to use the mouse to manage commits in some GUI.
So I’ve written a tiny shell script which I’ve added as a custom git command. The git stop
command I wish I had.
The Script
Using the help of our new friend ChatGPT, since I don’t usually write shell scripts, I asked it to write it for me to avoid spending an hour battling with the syntax to make it work. Of course it delivered, and even with a detailed explanation of how to run it.
#!/bin/sh
# Check if any arguments were provided
if [ $# -eq 0 ]; then
echo "Error: No arguments provided"
exit 1
fi
# Stage all files in the current directory except for the specified files
git add .
for file in "$@"
do
# Unstage the file
git reset HEAD "$file"
Done
You need to name the file something like git-my-custom-cmd
(no extension) which you’ll run as git my-custom-cmd
. In my case I named it git-stop
. Then you’ll have to make it executable with this simple command:
chmod +x git-my-custom-cmd
Custom Git Command
In fact, Git already has what it needs to recognise the command due to the name we gave our script. This guy has done a magnificent job explaining how that works in an in-depth article about the inner-workings of custom git commands.
All we have to do is just to make it globally accessible within your shell, which in simple terms means it’s within a directory that exists in your $PATH
. So you either (1) create it in one of the directories already in there, or (2) add the directory where you’ve created it to the $PATH
.
If you’re familiar with shells you already know what to do, otherwise here are the two options above explained:
Method 1
Technically, you can just put it in any of the directories already in your path which you can see running echo &PATH
(they’re separated by colons), but you preferably should stick with /usr/local/bin
.
Method 2
This one requires editing your shell config file which is usually within your $HOME
folder (or its short form ~
), adding the following line to it:
export PATH="path-to-your-directory:$PATH"
Some of the most common shells are Bash that use the .bashrc
file for configuration, Zsh config file is typically called .zshrc
, Fish shells usually use config.fish
, etc…
To check which shell you’re using, run echo $SHELL
. If it’s bash for example, your config file is typically located in ~/.bashrc
which is short for /Users/<user>/.bashrc
.
For instance, some people like to dedicate a directory in their home folder for git utility scripts or this sort of stuff. Something like ~/git-scripts
to which the line you’ll have to add looks like:
export PATH="$HOME/git-scripts:$PATH"
# or
export PATH="~/git-scripts:$PATH"
Now go run it. You can give it multiple files as well.
git stop .env.staging some/other/polluted/file.js