I am well aware that when writing a pipeline script for a Jenkins job, good practice is to reclone a repo every time you run the job, however I do find myself desiring to just pull the branch content or checkout a revision and just run the job on that (in some cases at least).
However I want to let the user specify either a hash or a branch name to check out.
If it is a branch name, then a git pull is in order, since the user probably pushed new content to try out with the job.
But if the specified revision is a hash then we will be in detached HEAD mode, and git pull
will fail with
You are not currently on a branch.
Please specify which branch you want to merge with.
See git-pull(1) for details.
git pull <remote> <branch>
How to silence this error or only run git pull
if it was a branch that was specified ? Or circumvent this problem altogether ?
I have found some code to check if the passed revision is a branch but I find it a bit fidgety :
git show-ref --verify --quiet refs/heads/${params.revision}
if %ERRORLEVEL% EQU 0 git pull
Any more natural suggestions ?
1
Note: throughout this answer I will use <commit-ID-or-branch-name>
to indicate what is being passed in. Since we don’t know if it’s a commit ID or branch name, all commands below need to work for both cases. This answer also assumes the shell is Bash. (Adjust the syntax accordingly if you’re using a different shell.)
In the case where a branch name is provided, let’s first make sure you don’t have a local copy of that branch. We can use Rahul Sharma’s comment’s syntax for returning true even if the command fails, which it would do when a commit ID is used instead of a branch name:
git switch --detach
git branch -D <commit-ID-or-branch-name> | true
If a branch was passed in, the above commands simply delete that local branch. If the local branch didn’t already exist, or if a commit ID was passed in, then nothing happens.
The following set of 2 commands will now work for both a commit ID and a branch name:
git fetch origin <commit-ID-or-branch-name>
git checkout <commit-ID-or-branch-name>
Note that the checkout
command can be used on both a commit ID and a branch name without specifying the --detach
option. If your pipeline doesn’t need to create new commits on a branch, then it may be (slightly) better to always use a commit ID even if you are checking out a branch, in which case you should use the --detach
option with checkout
, or, you can also use the switch
command:
git fetch origin <commit-ID-or-branch-name>
git switch --detach <commit-ID-or-branch-name>
Side Notes:
- Checking out a specific commit is slightly different than
pull
. Since the premise of your question is comparing pulling with a fresh clone, then this would be functionally equivalent, and in fact conceptually “cleaner” thanpull
, since it omits the possibility of unknown local commits tainting the build. If they did exist, they will also be removed above with the deletion of that branch. - The above commands assume a clean status. If you find the pipeline failing because the status does not start out clean, consider using a clean command first, or the force option with checkout.
2