Search code examples
command-line-interfacezshoh-my-zshzshrczsh-alias

Why do I need to run my zsh alias twice to assign vcs_info to a variable?


I'm trying to create a zsh alias pog that force-pushes a local branch to a non-existent remote branch of the same name, creating it in the process.

While I've been able to get this to work -- sort of -- it requires me to run the alias function twice instead of once. Since the purpose of this alias is to shorten the number of steps required to perform this routine git task, I'm looking for help with refactoring my code so that it performs correctly the first time around.

Here is the alias:

function pog() {
  autoload -Uz vcs_info
  precmd() { vcs_info }
  GB="$(echo ${vcs_info_msg_0_} | ggrep -Pio '(?<=\(git\)-\[).*(?=\]-)')"
  git push --set-upstream origin ${GB}
}

Here is an example of how it currently (mis-)behaves:

Documents/dev/test  test-123 ✔                                                              7m
▶ pog
fatal: The current branch test-123 has no upstream branch.
To push the current branch and set the remote as upstream, use

    git push --set-upstream origin test-123


Documents/dev/test  test-123 ✔                                                             7m  ⍉
▶ pog
Total 0 (delta 0), reused 0 (delta 0), pack-reused 0
remote:
remote: Create a pull request for 'test-123' on GitHub by visiting:
remote:      https://github.com/mr-potato/test/pull/new/test-123
remote:
To github.com:mr-potato/test.git
 * [new branch]          test-123 -> test-123
Branch 'test-123' set up to track remote branch 'test-123' from 'origin'.

What I've tried so far

  • Tried removing quotes around the definition of GB -- no change in behavior
  • Tried including GB assignment inside of precmd -- no change in behavior

Beyond these attempts, I'm a bit unsure what else to do and would greatly appreciate some insight & assistance to make this handy function a reality. Thank you!


Solution

  • The second line in the function is setting up another function, precmd(), which is usually used to add information to the zsh prompt. It is not calling vcs_info or setting the vcs_info_msg_0_ variable - that happens later, when zsh is generating the prompt. That's why it's available the second time around.
    Try this (nb: I did not test it):

    function pog() {
      autoload -Uz vcs_info
      vcs_info
      GB="$(echo ${vcs_info_msg_0_} | ggrep -Pio '(?<=\(git\)-\[).*(?=\]-)')"
      git push --set-upstream origin ${GB}
    }
    

    If that works, you may be able to optimize it further by getting vcs_info to return just the git branch. This goes in ~/.zshrc:

    autoload -Uz vcs_info
    zstyle ':vcs_info:git:*' formats '%b'
    function pog() {
      vcs_info
      git push --set-upstream origin "${vcs_info_msg_0_}"
    }
    

    This is also untested.