Another issue both versions have is that they will not tolerate head being NULL.
Don't be afraid of double pointers, although they may seem overly clever at first glance, they can be really helpful for situations like this. Linus's code is considerably shorter, and not particularly difficult to debug or to understand, assuming you understand double pointers.
Another case where double pointers can be really useful is in the interface for linked lists. I.e.
remove_list_entry(node** head, node* entry) { [...] }
Defining the interface that way allows properly removing the last entry from the list. Workarounds like making a list struct and passing a pointer to that are just double pointers in disguise. Returning the new head is error prone, since you can easily forget to reassign it.Double pointers for life!