60

I am cloning a git repository in a script like this:

git clone https://user:password@host.com/name/.git

This works, but my username and my password! are now stored in the origin url in .git/config.

How can I prevent this, but still do this in a script (so no manual password input)?

Nathan
  • 733
  • 1
  • 5
  • 7

5 Answers5

35

The method that I use is to actually use a git pull instead of a clone. The script would look like:

mkdir repo
cd repo
git init
git config user.email "email"
git config user.name "user"
git pull https://user:password@github.com/name/repo.git master

This will not store your username or password in .git/config. However, unless other steps are taken, the plaintext username and password will be visible while the process is running from commands that show current processes (e.g. ps).

As brought up in the comments, since this method is using HTTPS you must URL-encode any special characters that may appear in your password as well.

One further suggestion I would make (if you can't use ssh) is to actually use an OAuth token instead of plaintext username/password as it is slightly more secure. You can generate an OAuth token from your profile settings: https://github.com/settings/tokens.

Then using that token the pull command would be

git pull https://$OAUTH_TOKEN:x-oauth-basic@github.com/name/repo.git master
FGreg
  • 530
  • 3
  • 10
  • Unofrtantly I cannot use auth tokens. I am not using github but a private server. – Nathan Nov 16 '16 at 07:20
  • 3
    Should also be noted that the username and password will be visible in, e.g., `ps` while the pull runs (at least unless you've prevented users from seeing each others' processes) – derobert Nov 21 '16 at 17:30
  • Points for oath usage. It's exactly what I needed in production/staging/dev. – RobotHumans Sep 11 '18 at 14:39
  • a million thanks to you buddy. wasted hours n hours n finally your answer came to resue. :thumbsup – JasdeepSingh Feb 28 '19 at 15:07
  • 1
    Note that in this solution reserved characters need to be escaped. e.g. `myp@ssword` should be provided as: `myp%40ssword` – Marinos An Jan 07 '20 at 13:12
28

IMO the best solution is using a custom GIT_ASKPASS helper and deliver the password as another environment variable. So for example, create a file git-askpass-helper.sh as:

#!/bin/sh
exec echo "$GIT_PASSWORD"

and then run git clone https://username@hostname/repo with environment variables GIT_ASKPASS=/path/to/git-askpass-helper.sh and GIT_PASSWORD=nuclearlaunchcodes.

This has the advantage that the password won't be visible in the process list too.

intgr
  • 420
  • 4
  • 5
  • +1 for creative solution. This would be a little more secure than the `git pull` solution and allow you to store the plaintext password as a secret in your automated deploy tool of choice. – FGreg Jun 14 '18 at 17:43
  • 1
    Did not work. Still asks for a password on `git clone` – Marinos An Dec 18 '19 at 15:13
  • Any way to make it work in windows? I think i saw the solution to replace the .sh file with exe, but i do not want to (Cannot stress enough) commit an exe into my repo – Pranav Raj Feb 04 '20 at 21:26
  • @PranavRaj I think you should be able to port it to a `.bat` or `.cmd` file as well but I'm not familiar with that syntax. – intgr Feb 05 '20 at 13:56
  • For anyone else looking for a cross platform solution: I used the https://github.com/libgit2/libgit2sharp/wiki nuget package and I was able to build a .net core app which worked on both windows and linux :) Instead of storing the password in my code, I stored it in the key vault and inside the code accessed the secret - so not saving git password as a plain text anywhere :) – Pranav Raj Feb 05 '20 at 20:16
21

After going over dozens of SO posts, blogs, etc, I tried out every method, and this is what I came up with. It covers EVERYTHING.

See The Git Credentials & Private Packages Cheatsheet

These are all the ways and tools by which you can securely authenticate git to clone a repository without an interactive password prompt.

  • SSH Public Keys
    • SSH_ASKPASS
  • API Access Tokens
    • GIT_ASKPASS
    • .gitconfig insteadOf
    • .gitconfig [credential]
    • .git-credentials
    • .netrc
  • Bonus: Works with Private Packages
    • node / npm package.json
    • python / pip / eggs requirements.txt
    • ruby gems Gemfile
    • golang go.mod

Best options for no plaintext storage

From what's asked here either SSH Keys, GIT_ASKPASS, or git credential store using the OS Keychain manager might be the best choice.

Since GIT_ASKPASS is probably the least understood of the 3, I'll detail that here - and the others are in the cheatsheet.

GIT_ASKPASS

How to create an GIT_ASKPASS script:

echo 'echo $MY_GIT_TOKEN' > $HOME/.git-askpass

How to use it:

export MY_GIT_TOKEN=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
export GIT_ASKPASS=$HOME/.git-askpass
git clone https://token@code.example.com/project.git

The script receives stdin in the form of:

Password for 'scheme://host.tld':

The script receives Git ENVs such as:

GIT_DIR=/Users/me/project/.git
GIT_EXEC_PATH=/usr/local/Cellar/git/2.19.0_1/libexec/git-core
GIT_PREFIX=

More details in the cheatsheet.

coolaj86
  • 911
  • 2
  • 10
  • 19
15

You can enter your connection creds in your ~/.netrc file. Something along the lines of:

machine host.example.net
login bart
password eatmyshorts

Just make sure to chmod that file to 600. If you're using windows, the following link may be useful: https://stackoverflow.com/questions/6031214/git-how-to-use-netrc-file-on-windows-to-save-user-and-password

Personally, I have a tendency to use SSH keys for auth purposes (if you are allowed, of course).

Brett Levene
  • 776
  • 6
  • 9
0

Store your token or password somewhere safe, e.g. pass.

Then use a bash script to map git host to your password store, e.g.:

#!/usr/bin/env bash
# assuming "get" action from git and a config like this
# git config --global credential.helper $XDG_BIN_HOME'/git_credentials_from_pass $@'
while IFS= read -r line
do
  echo "$line"
  if [[ "$line" =~ host=.*github.com.* ]]; then
      echo "username=your_user_name"
      echo "password=$(pass show token_github.com/your_username)"
  #else ...
  fi
done

Change your_username and token_github.com the way you set it up.

Source.