1

I regularly need to replace my default git osxkeychain credentials, using the command-line. The way I do it manually is as follows:

git credential-osxkeychain erase <Enter>
host=github.com <Enter>
protocol=https <Enter>

password=foo <Enter>
username=bar <Enter>
<Enter><Enter>

And then that process again, except with git credential-osxkeychain store and the new credentials. I'd like to automate it, something like

alias git_newcred='git credential-osxkeychain erase; host=github.com; protocol=https;git credential-osxkeychain erase; host=github.com; protocol=https;'

Where the ; newlines are in place of the enter key. However, as it is this fails silently.

The beginning of the read_credential method in the source looks like this:

while (fgets(buf, sizeof(buf), stdin)) {
    char *v;

    if (!strcmp(buf, "\n"))
        break;
    buf[strlen(buf)-1] = '\0';

How do I alias multi-line entry, which is part of a single command? Or is there a better way to do this?

(Using zsh, but I don't think there's anything zsh-specific going on.)

Josh Friedlander
  • 10,870
  • 5
  • 35
  • 75
  • If you are using `zsh`, the `bash` tag isn't appropriate. – chepner Apr 06 '20 at 13:40
  • I figured since it isn't zsh-specific, and zsh is a subset of bash, isn't `bash` the better tag (maybe instead of `zsh`)? The way that Python3 questions are just tagged `python` unless they involve some specific quirk of 3 – Josh Friedlander Apr 06 '20 at 14:15
  • `zsh` is most certainly *not* a subset of `bash`; it's an entirely different shell. They share many features in common, and even a good amount of syntax, but there is `bash` code that works differently or not at all if you attempt to execute it with `zsh`, and there is *tons* of `zsh` code that `bash` cannot execute. It would be more accurate (though still wrong) to call `zsh` a superset of `bash`. – chepner Apr 06 '20 at 14:18
  • OK, point taken. I'll untag. – Josh Friedlander Apr 06 '20 at 15:31

1 Answers1

3

You should use a function, not an alias. After you run git, the rest of the data is input to that command, not additional commands to be run by the shell. You can do that with a here document

git_newcred () {
    git credential-osxkeychain erase <<EOF
host=github.com
protocol=https
password=foo
username=bar
EOF
}

or with a pipe.

git_newcred () {
    # POSIX-compatible version
    # printf '%s\n' ... | git credential-osxkeychain
    print -l "host=github.com" "protocol=https" "password=foo" "username=bar" | git credential-osxkeychain
}
chepner
  • 497,756
  • 71
  • 530
  • 681
  • This is really helpful, thank you. Is there any way I could do it where it would chain `erase` && `store` new credentials, and take username and password as $1 and $2 arguments? Also, should this be in my .zshrc or a separate file (or does it not matter)? – Josh Friedlander Apr 06 '20 at 15:56
  • I would put it in `.zshrc`. You can replace `bar` with `$1` and `foo` with `$2`. As for chaining, the body of the function can consist of an arbitrary sequence of commands; just run `git credential-osxkeychain` on the line following `EOF`. – chepner Apr 06 '20 at 15:59