In Haskell, that’s “unit” or the empty tuple. It’s basically an object with no contents, behavior, or particular meaning, useful for representing “nothing”. It’s a solid thing that is never a surprise, unlike undefined or other languages’ nulls, which are holes in the language or errors waiting to happen.
You might argue that it’s a value and not a function, but Haskell doesn’t really differentiate the two anyway:
value :: String
value = "I'm always this string!"
funkyFunc :: String -> String
funkyFunc name = "Rock on, "++name++", rock on!"
Is value a value, or is it a function that takes no arguments? There’s not really a difference, Haskell handles them both the same way: by lazily replacing anything matching the pattern on the left side of the equation with the right side of the equation at runtime.







What was happening before was this: Git received your commits and ran the shell script. It directed the script’s output stream back to Git so that it could relay it back over the connection to display on your local terminal with
remote:stuck in front of it. Backgrounding thenpxcommand was working, the shell was quitting without waiting fornpxto finish. However, Git wasn’t waiting for the shell script to finish, it was waiting for the output stream to close, andnpxwas still writing to it. You backgrounded the task but didn’t givenpxa new place to write its output to, so it kept using the same output stream as the shell.Running it via
bash -cmeans “don’t run this under this bash shell, start a new one and have it just run this one command rather than waiting for a human to type a command into it.”The & inside the quote is doing what you expect, telling the subshell to background this task. As before, it’ll quit once the command is running, as you told it not to wait.
The last bit is
&> /dev/nullwhich tells your original, first shell that you want this command to write somewhere else instead. Specifically, the special file/dev/null, which, like basically everything else in/dev/, is not really a file, it’s special kernel magic. That one’s magic trick is that when you write to it, everything works as expected except all the data is just thrown away. Great for things like this that you don’t want to keep.So, the reason this works is you’re redirecting the
npxoutput elsewhere, it just goes into a black hole where no one is actually waiting for it. The subshell isn’t waiting for the command to finish, so it quits almost immediately. And then the top level shell moves on after the subshell has finished.I don’t think the subshell is necessary, if you do
&> /dev/null &I think it’d be the same effect. But spawning a useless shell for a split second happens all the time anyway, probably not worth worrying about too much.