bashgitshellrebasegit-rebase

How to pass a shell function to `git rebase --exec`


In bash, to pass a variable or function to a child process, you need to export it.

#!/bin/bash

f() { echo hello; }

# calling shell function `f` in child process
bash -c "f" # bash: f: command not found

# export the function
export -f f
bash -c "f" # "hello"

However, I can't seem to achieve the same result with git rebase --exec

#!/bin/bash

f() { echo hello; }

# export the function
export -f f
git rebase --exec "f" # does not work
git rebase --exec "bash -c 'f'" # does not work

I know I could declare the function inline: git rebase --exec 'f() { echo hello; }; f' or put the function in another script and call it: git rebase --exec './f.sh'

Is there a way to make it work? What am I missing?


Solution

  • Here is my solution. Thanks to @CharlesDuffy for his help.

    #!/usr/bin/env bash
    
    f() {
      for i in "$@"; do
        echo "$i"
      done
    }
    
    printf -v cmd_q '%q ' "$(declare -f f); f" # serialise function f
    export cmd_q
    printf -v args '%q ' "$@" # serialise arguments f
    export args
    
    # remove -r --root and adapt to your needs here
    git rebase -r --root --exec $'bash -c "eval $cmd_q \'$args\'"'