Git shortcut to pull with clone if no local there yet?

GitJenkins

Git Problem Overview


Is there a one-command way to get an up-to-date mirror of a remote repo? That is

  • if local repo not there yet: clone
  • if it's there: pull

I know I could script this around (e.g if [ -d repo ]; then (cd repo && git pull); else git clone $repourl;fi ) , but I need the simplest possible cross-platform way (actually used for Jenkins-CI, which I know does this by default, however I need 2 repos for which support is limited).

Git has similar shortcuts for other things (eg. checkout -b, and pull itself), so I'm wondering if I missed something. Thanks!

Git Solutions


Solution 1 - Git

There is not, given that the commands which operate on existing repos all assume that they're being run inside a given repo.

That said, if you're running in a shell, you could simply make use of the shell built-ins. For instance, here's bash:

if cd repo; then git pull; else git clone https://server/repo repo; fi

This checks to see if repo is a valid directory, and if so, does a pull within it; otherwise it does a clone to create the directory.

Solution 2 - Git

The cleanest one-liner might be

git -C repo pull || git clone https://server/repo repo

Solution 3 - Git

git -C repo pull will only work on git 1.8.5 or above. To achieve this on earlier versions, try:

remote_repo=https://server/repo
local_repo=repo

if [ -d $local_repo/.git ]; then pushd $local_repo; git pull; popd; else git clone $remote_repo; fi

Solution 4 - Git

If upgrading git is not an option, and you don't want to pass an argument for a repo, a scripting approach could be:

#!/bin/bash

function clone_pull {
  DIRECTORY=$(basename "$1" .git)
  if [ -d "$DIRECTORY" ]; then
    cd "$DIRECTORY"
    git pull
    cd ../
  else
    git clone "$1"
  fi
}

clone_pull https://github.com/<namespace>/<repo>
# or
clone_pull [email protected]:<namespace>/<repo>.git

Solution 5 - Git

git pull knows from where to clone because the local repo has a remote registered in its local config. It operates from a working tree.

But git clone doesn't, it must have an explicit remote url passed in parameter in order to clone. It operates outside the working tree.

The main reason for such a shortcut to not exist is that:

  • you git init rarely for a given repo: it is a one-time command in the life of the repo.
    Plus it might need additional command to be complete: if you havesubmodules, for instance, you would need to add a git submodule update --init.
  • you git pull often within a given repo. git pull is in itself a shortcut (for git fetch + git merge). Even git pull --rebase is another shortcut for git fetch + git rebase.

Considering the number of times you are to use git init, such a shortcut is not an high priority.

So a script remains the surest way to define what you need.

Solution 6 - Git

Since you mentioned Jenkins, it is possible to clone or pull using the Jenkins SCM API. The checkout method does exactly what you want.

You can run it from a groovy script like so:

dir (targetFolder) {
  checkout(scm: [$class: 'GitSCM', branches: [[name: 'master']], ...])
}

Note that it does not check out the specified branch in the git sense, but rather leaves the workspace on a detached head at the corresponding commit.

Solution 7 - Git

Here is another 1-liner. In contrast to other solutions here, this code does not output an error in the terminal:

(test -d my-repo && git -C my-repo pull --rebase) || \
  git clone https://github.com/my-repo my-repo

Here is a variation where the repo and source URL are variables, so you don't need to repeat the repo-folder three times:

DIR=my-repo && ORIGIN=https://github.com/my-repo/ && \
  (test -d $DIR && git -C $DIR pull --rebase) || git clone $ORIGIN $DIR

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestioningerView Question on Stackoverflow
Solution 1 - GitAmberView Answer on Stackoverflow
Solution 2 - GitjhrmnnView Answer on Stackoverflow
Solution 3 - GitNoam ManosView Answer on Stackoverflow
Solution 4 - GitandylukemView Answer on Stackoverflow
Solution 5 - GitVonCView Answer on Stackoverflow
Solution 6 - GityoyoView Answer on Stackoverflow
Solution 7 - GitPhilippView Answer on Stackoverflow