DEV Community

Cover image for Multitasking like a pro with the WIP commit
Aziz
Aziz

Posted on

Multitasking like a pro with the WIP commit

Intro

Multitasking sucks and should be an exception 99% of the time for coding work. But alas, life does what it wants, so sometimes when coding, you have to urgently put your current work away to work on something else.

You may already know of the popular git stash command but did you know there’s an arguably better way?

In this article, I talk about the The WIP (work in progress) commit and the git commands that enable it, why it’s more flexible than other choices, and also some aliases with cool names.


The WIP Commit Sales Pitch

You’re working on some branch and have some unstaged changes. Imagine the following scenarios:

  • You want to share your progress with a colleague to collaborate on a tough issue you’re stuck on.

  • A sudden high priority production bug arises and you need to work on it ASAP while you delegate your current branch to someone else.

  • The feature you’re working on is unfinished but you’re done for the day so you want to push your work to your branch to keep it safe in the cloud.

  • You want to simply transfer your current work to a different machine to continue working there.

The common thing between all of these is that you need to save your work somewhere right now. You don’t care about commit messages, pre-commit hooks, CI pipelines, or anything else.

Well, guess what? The WIP commit removes all of that from your way and allows you to truly just send it and forget it.

WIP commit skips unnecessary steps

Here’s the command for it:

git add -A; git rm $(git ls-files --deleted) 2> /dev/null; git commit --no-verify --no-gpg-sign --message "--wip-- [skip ci]"
Enter fullscreen mode Exit fullscreen mode

Yeah, it’s pretty terrifying. The cool part is, some smart people on the internet thought of it for us so we don’t have to worry about it. The command comes from the ohmyzsh git plugin aliases.

If you’re curious, here’s a breakdown of what each part of the command does:

Breakdown of the gwip alias

Demo & Usage

There are three aliases you should know:

  • gwip
  • gunwip
  • gunwipall

You can use the gwip alias to stage everything and create a WIP commit in one go. Here’s a demo:

Using the gwip command

Note that you still have to git push it manually if you want to track it remotely. If you have pre-push hooks, you can skip those with git push --no-verify. Use this power wisely.

Likewise, you can use gunwip to unwip (soft reset) the last WIP commit you’ve made. Here’s a demo:

Using the gunwip command

Finally, you can use gunwipall which unwips (soft resets) all WIP commits you have in your current branch if you happened to have more than one.

Why?

  • Relevant work is stored in the relevant branch
  • WIP commits are gone when you delete the branch, so you don’t have a list of rotting old stashes.
  • No copy-pasting of files like with apply
  • Your work is saved on the cloud

Why not git stash?

Although git stash is another really handy command, stashing doesn’t work for this use case for a few reasons:

  • It’s only local to your machine
  • It’s not associated with any branches as it’s stored in your stash list
  • Applying a stash which is not at the top of your list complicates your command.
  • Your stash list can get messy with forgotten stashes (be honest with yourself, how many do you have right now?)

Why not patch?

Patches solve pretty much the same issue, but they aren’t as useful as gwip for the following reasons:

  • They’re not associated with a branch.
  • They involve copy-pasting
  • You have to track them manually. You’re not able to push a patch, otherwise it would be called a commit.
  • Did I mention they involve copy-pasting?

Setting it up

Using Ohmyzsh

If you’re using Ohmyzsh, you can edit your .zshrc file’s plugins to include git like so:

Notice the red arrow helping you to find the word git under plugins, in case that was difficult

Afterwards, you’ll want to run source ~/.zshrc or quit your terminal and open it up again for changes to take effect. By the way, the git plugin for OMZ includes a ton of really helpful aliases that you’d do yourself a favor by checking out its docs.

If you’re not using OMZ, simply read the next section about setting it up manually with aliases.

Manually

Add the following to your .zshrc or .bashrc file:

alias gwip='git add -A; git rm $(git ls-files --deleted) 2> /dev/null; git commit --no-verify --no-gpg-sign --message "--wip-- [skip ci]"'

alias gunwip='git rev-list --max-count=1 --format="%s" HEAD | grep -q "\--wip--" && git reset HEAD~1'

# Similar to `gunwip` but recursive "Unwips" all recent `--wip--` commits not just the last one
function gunwipall() {
  local _commit=$(git log --grep='--wip--' --invert-grep --max-count=1 --format=format:%H)

  # Check if a commit without "--wip--" was found and it's not the same as HEAD
  if [[ "$_commit" != "$(git rev-parse HEAD)" ]]; then
    git reset $_commit || return 1
  fi
}
Enter fullscreen mode Exit fullscreen mode

Now reload your config file using source ~/.zshrc (or .bashrc or whatever you’re using) and you should now have the aliases ready for use.

Conclusion

WIP commits make everyone’s lives easier by allowing you to simply send it and forget it. I hope you find it useful. Let me know your opinion!

Top comments (0)