I thought the shell script was actually a really great way of introducing you to the subject. You can basically look at the script, make out the "hot" part, optimize that part and you're done.
It's not calling the git command that's problematic, it's calling an external command at all. So you pretty much have to recode the hot part in another language, where you just manipulate buffers instead of piping stuff around.
I did exactly that but my SHA-1 (in Ruby) is ending up different than Git's. Even weirder, when I take the header + body, and use an online SHA-1, I get a third and different value! (Not equal to git-hash-object nor to mine in Ruby). Is the body supposed to be modified to add LEDGER content?
Look again at Object Storage under the Git Objects link and you should get it, you're probably not quite matching what it does, it is a simple SHA1 so you're probably just missing one little part of the string to hash. You're on the right track - test getting the hashes to match first with git hash-object, but once you have done that you just need to solve it faster and recover when you discover that someone else got there first.
It is possible in ruby, that's what I used first, though the ref implementation is in ruby, so a single process may not cut it unless you are lucky. Keep trying too if you are solving it but not quite making it in time as you're competing against a variable time to complete on the other side.
This was the part that I stumbled on for a few hours late at night and kept me up. Next morning, when investigating what git hash-object did, it was obvious. should have just went to sleep.
You don't have to use bash, or just one process. You can completely replace their solution as long as you do roughly the same thing and they can run your binary (C, python, ruby, java, whatever).