Git Bash Script Check Working Tree - bash

Is there a way in Git Bash to check if the working tree is clean, that is no uncommitted changes or untracked files?
I'm working on a bash script for my group to automate the process of daily rebasing working branches. Unclean working trees is a common problem. I can manually correct the problem by executing git checkout .. This would have the desired result most of the time, but not always, so I need to be able to have my script programatically check that the working directory/tree is clean.

The git-sh-setup script included with git contains a number of useful functions for working with git repositories. Among them is require_clean_work_tree:
require_clean_work_tree () {
git rev-parse --verify HEAD >/dev/null || exit 1
git update-index -q --ignore-submodules --refresh
err=0
if ! git diff-files --quiet --ignore-submodules
then
echo >&2 "Cannot $1: You have unstaged changes."
err=1
fi
if ! git diff-index --cached --quiet --ignore-submodules HEAD --
then
if [ $err = 0 ]
then
echo >&2 "Cannot $1: Your index contains uncommitted changes."
else
echo >&2 "Additionally, your index contains uncommitted changes."
fi
err=1
fi
if [ $err = 1 ]
then
test -n "$2" && echo >&2 "$2"
exit 1
fi
}
This is in addition to being able to check the output from git status --porcelain and/or git status -z if you need to be more specific about what the state currently is.

Related

Pipeline to fail if previous commit was rebased

I was able to run a pipeline to check if rebased was required or not when a commit is merged onto master, but once the commit is rebased and synced with master branch, it passes the pipeline. My script is comparing the 2 parents commits when the merge is done. Searching for ways to make the pipeline fail if commit was rebased and merged onto bitbucket master branch.
My script is as follows:
#!/bin/bash
trg=$1
itg=$2
parent_commit_count=$(git cat-file -p $BITBUCKET_COMMIT | grep -o -i parent | wc -l)
echo "Number of parent commits:"$parent_commit_count
if [ "${parent_commit_count}" = "2" ]
then
echo "Validating master branch graph shape"
fi
if [[ -z $trg ]]; then
trg=HEAD
fi
if [[ -z $itg ]]; then
itg=master
fi
ret=$(git rev-list $trg..$itg)
if [[ -z $ret ]]; then
echo "No rebase required, sexy graph is maintained."
else
echo "Commit $BITBUCKET_COMMIT needs to be rebased to absorb the following changes:"
for r in $ret
do
echo $r
done
exit 1
fi
Pipeline:
branches:
master:
- step:
name: Branch Trigger to Master
script:
- echo "Checking Merge Commit"
- chmod +x MergeCommitCheck.sh && ./MergeCommitCheck.sh

Push nuget package only if the package version matches the Tag on Git's master branch

In our development environment, we have set up a NuGet local server (BaGet). We have adopted the Gitflow idea. When a library is ready to be released on Baget, the developer should first increase the Tag on the master branch (which needs to be approved first via a pull-request), then push the library to the Baget. We do this to keep the version of Git and Nuget in sync.
The process of keeping versions in sync (Git tag & NuGet version) is controlled manually by the developer and sometimes some team members forget to define the Git version tag and just push the library to Baget.
It would be a great help if the script could check the Current Git Tag before pushing the library to the Baget server, and only push it if the Tag and Version are the same. This can prevent pushing a version without matching Tag on git.
We use this script for pushing to Baget:
#!/bin/bash
clear
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
cd $DIR
ostype=`uname`
KEY=$NUGET_KEY
SOURCE=$NUGET_URL
while :
do
clear
echo "Input your package version: "
read version
Common="Dayan.Common/bin/Debug/Dayan.Common."$version".nupkg"
dotnet nuget push $Common -s $SOURCE -k $KEY
echo "press enter to continue ..."
read
done
Can I somehow check use git commands in the bash to get the Tag of the last commit on the master branch of the project, and check it with the user input for version?
One way to make that check would be to use the git command rev-list.
This command will output the commit SHA of the most recent commit:
$ git rev-list -n 1 HEAD
dfe4a9989b33e97f25645d79fd62900cc3209ec7
While this command will output the commit SHA of the tag 3.1.5:
$ git rev-list -n 1 "3.1.5"
a35117a201290b63b53ba6372dbf8bbfc68f28b9
The following example script should get you started:
#!/bin/bash
echo "Input your package version: "
read version
last_commit=$(git rev-list -n 1 HEAD 2>/dev/null)
last_commit_result=$?
if [ "$last_commit_result" != "0" ]; then
echo "Failed to get the SHA of the most recent commit"
exit 1
fi
version_commit=$(git rev-list -n 1 "$version" 2>/dev/null)
version_commit_result=$?
if [ "$version_commit_result" != "0" ]; then
echo "There is no commit with the tag: $version"
exit 1
fi
if [ "$last_commit" = "$version_commit" ]; then
echo "The most recent commit has the tag: $version"
else
echo "The most recent commit does NOT have the tag: $version"
fi
If you also want to make sure the script is only run from master then add this near the script's start:
active_branch=$(git branch --show-current 2>/dev/null)
active_branch_result=$?
if [ "$active_branch_result" != "0" ]; then
echo "Failed to get the active branch"
exit 1
elif [ "$active_branch" != "master" ]; then
echo "The active branch is not master"
exit 1
fi

Git server-side pre-receive hook

I am working on enforcing git pre-commit hook as a server-side pre-receive or an update hook and unable to find proper examples on achieving it.
I was able to successfully implement/test the pre-commit hook
#!/bin/bash
echo "Running pre-commit hook"
checks=($APPSETTING_DEVPASSWORD $APPSETTING_DEVUSER $APPSETTING_DEVPASS_ELMAH) # create an array
git diff --cached --name-status | while read flag file; do
if [ "$flag" == 'D' ]; then continue; fi
for word in ${checks[#]}
do
if egrep -q "$word" "$file"; then
echo "ERROR: Disallowed expression \"${word}\" in file: ${file}" >&2
exit 1
fi
done
done
I am trying to translate the same into server-side hook where the hook should look for the checks array and exit with 1 if the diff contains the values in the checks array.
Information Found online
Bitbucket server contains only the base repository and doesn't contain the files from the local repository, Hence the diff of the commit sha needs to be evaluated while pushing.
Can someone please help translate the same into a server-side git hook.

Access the changes files in git pre-receive hook & search for string pattern

I have one pre-commit script/hook working just fine to search for specific string pattern in the files and reject the commit. I'm not sure how to read the incoming files in the pre-receive script to search for string pattern.
My pre-commit scripts looks like this:
#!/usr/bin/env bash
if git rev-parse --verify HEAD >/dev/null 2>&1
then
against=HEAD
else
# Initial commit: diff against an empty tree object
EMPTY_TREE=$(git hash-object -t tree /dev/null)
against=$EMPTY_TREE
fi
FILES=$(git diff --cached --name-only $against)
if [ -n "$FILES" ]; then
string1 = $(grep -rE --line-number 'access_key' $FILES)
if [ -n "$string1" ] then
echo "string1 there so reject it"
while true; do
exit 1;
done
fi
fi
I'm not sure how to convert this to a pre-receive hook script on git server side.
I've been trying this for hours with no luck. Can someone please help me out here?

unexpected operator [: git: in bourne shell script 'if' conditional statement

I've watched an excellent shell scripting course through a multitude of videos. Now that I think I am fairly familiar with the Bourne shell, I decided to write my first shell script.
Script goal: check if git working directory is clean. If so, overwrite working directory to a branch named deployment. Finally, push the deployment branch to origin.
I ended up with this code:
#!/bin/sh
######################################################
# Deploys working directory to git deployment branch.
# Requires that the working directory is clean.
######################################################
#check if the working directory is clean
if [ git diff-index --quiet HEAD ]
then
if [ git branch -f deployment ]
then
if [ git push origin deployment ]
then
echo
echo "OK. Successfully deployed to git deployment branch."
echo
exit 0 #success
else
echo
echo "Error: failed to push deployment branch to origin."
echo
exit 1 #failure
fi
else
echo
echo "Error: failed to create or overwrite deployment branch."
echo
exit 1 #failure
fi
else
echo
git status #show the status of the working directory
echo
echo "Error: working directory is not clean. Commit your changes first..."
echo
exit 1 #failure
fi
Unfortunately, this seems to give me an error: ./tools/deploygit: 9: [: git: unexpected operator
Why is this so? What operator am I using in if [ git diff-index --quiet HEAD ] that is unexpected?
As a bonus, do you have any suggestions or tips on how to improve the efficiency, logic or readability of this script?
In this statement:
if [ git diff-index --quiet HEAD ]
The [ is an alias for the test command, so what you're actually running is...
if test git diff-index --quiet HEAD ]
...which isn't what you mean. You don't need to use the test command in order to evaluate the result of a command; you should just do this:
if git diff-index --quiet HEAD
Take a look at the documentation for the if command:
$ help if
if: if COMMANDS; then COMMANDS; [ elif COMMANDS; then COMMANDS; ]... [ else COMMANDS; ] fi
The conditional argument to the if statement is command. Normally, the test command is used to make it look like other languages, but you can put any command there. Things that exit with a return code of 0 evaluate to true and anything else evaluates to false.

Resources