I have a pre-receive hook to check the naming convention for running Git project:
valid_branch_regex="^(master|release-[0-9]{4}-[0-9]{2}|[A-Z|0-9]{3,6}-[0-9]+-.*)"
while read oldrev newrev refname; do
echo "$refname : $oldrev ~ $newrev"
current_branch=$refname
short_current_branch="$(echo $current_branch | sed 's/refs\/heads\///g')"
done
message="There is something wrong with your branch name. Branch names in this project must adhere to this contract:\
$valid_branch_regex. Your commit will be rejected. You should rename your branch to a valid name and try again."
if [[ ! $short_current_branch =~ $valid_branch_regex ]]
then
echo "$message"
exit 1
fi
exit 0
The problem is that I want to bypass the branches which have been pushed before the script has been applied. Any idea to improve my current logic?
Thank you!
This might be a solution to this question:
valid_branch_regex="^(master|release-[0-9]{4}-[0-9]{2}|[A-Z|0-9]{3,6}-[0-9]+-.*)"
zero_commit="0000000000000000000000000000000000000000"
message="There is something wrong with your branch name. Branch names in this project must adhere to this contract: \
$valid_branch_regex. Your commit will be rejected. You should rename your branch to a valid name and try again."
while read oldrev newrev refname; do
echo "$refname : $oldrev ~ $newrev"
current_branch=$refname
short_current_branch="$(echo $current_branch | sed 's/refs\/heads\///g')"
done
message="There is something wrong with your branch name. Branch names in this project must adhere to this contract:\
$valid_branch_regex. Your commit will be rejected. You should rename your branch to a valid name and try again."
# Check for new branch or tag
if [ "$oldrev" == "$zero_commit" ]; then
short_current_branch="$(echo $current_branch | sed 's/refs\/heads\///g')"
else
echo "This is an existing branch, wont check the naming convention. \
Please be aware that the branch name should follow this contract: $valid_branch_regex"
exit 0
fi
if [[ ! $short_current_branch =~ $valid_branch_regex ]]
then
echo "$message"
exit 1
fi
exit 0
if [[ ! $short_current_branch =~ $valid_branch_regex ]]
then
echo "$message"
exit 1
fi
done
exit 0
Related
I am trying to create if statement which will check if repository with name X exists, if it doesn't => create it.
Made following code. It works, but when repository doesn't exists, then it shows error. I couldn't find any ways of removing that error in console. Make I was using &>/dev/null not in correct way...
myStr=$(git ls-remote https://github.com/user/repository);
if [ -z $myStr ]
then
echo "OMG IT WORKED"
fi
As soon as you completely silence git ls-remote I will suggest to check the exit code of the command ($?) rather than its output.
Based on your code you could consider a function in this way:
check_repo_exists() {
repoUrl="$1"
myStr="$(git ls-remote -q "$repoUrl" &> /dev/null)";
if [[ "$?" -eq 0 ]]
then
echo "REPO EXISTS"
else
echo "REPO DOES NOT EXIST"
fi
}
check_repo_exists "https://github.com/kubernetes"
# REPO DOES NOT EXIST
check_repo_exists "https://github.com/kubernetes/kubectl"
# REPO EXISTS
I was doing a script for myself to summarize commands I use daily in one handy script. So basically I ended doing it with a conditional checking if the .git folder exists first but I'd like to make it more interesting and like so understand better the loop. My desire is to have a variable like:
"output=$(git status)" and if the result is 0, continue depending on the statement. If the result is other than 0, break the loop and end the script with a message like "the actual directory hasn't a .git repo".
I let you my first idea of it but without the git status as I don't know how to add it neither where to. Thank you guys!
set -e
gitrepo=true
while [ $gitrepo == true ]; do
if [[ $? -ne 0 ]]; then
echo "not a git directory"
$gitrepo=false
else
read -p "Commit message: " commit
git commit -am "$commit"
fi
done
Try this: I did as Cyrus suggested:
#!/usr/bin/env bash
set -e
gitrepo=True
while [[ $gitrepo ]]; do
if [[ ! $? ]]; then
echo "not a git directory"
gitrepo=False
else
read -p "Commit message: " -r commit
git commit -am "$commit"
exit 0
fi
done
I am making a small automation to add all the .java files in my current directory but it has some flaws.
It pushes each file instead of pushing them all at once, it's okay If it asks the commit message for each file but I tried to git push the files outside the for loop.
#!/bin/bash
javafile=*.java
for i in $javafile;
do
if [[ "$i" == "$javafile" ]]
then
echo "No .java files"
else
git add $i
echo
echo "File $i added"
echo
echo "Write a message to commit"
read message
git commit -m "$message"
git push origin master
echo
echo "#############################################"
echo "$i pushed successfully"
echo "#############################################"
fi
done
The problem is the git push origin master inside the loop, consider the following script;
#!/bin/bash
javafile=*.java
filesCommit=0
# For each java file
for i in $javafile; do
if [[ "$i" == "$javafile" ]]; then
echo "No .java files"
else
# Add current file
git add $i
echo
echo "File $i added"
# Ask for commit message
echo
echo "Write a message to commit"
read message
# Commit single file with message
git commit -m "$message"
# Bumb counter to remember number of items
((filesCommit++))
fi
done
# If we've had atleast 1 file, push
if [[ "$filesCommit" -ge 0 ]]; then
git push origin master
echo
echo "#############################################"
echo "Pushed successfully; $filesCommit files"
echo "#############################################"
fi
Here I'm using a variable to count the number of files we've commited. Then, after the loop, we can push all those files
Due to some problems with a script which commits and pushes automatically, i'd like to implement a whitelist.
The plan is, that only commits with the pattern 'foo' and 'bar' in path, are allowed.
#!/bin/sh
WHITELIST="foo bar"
WRKDIR=/home/athur/workwork/test/repo
cd $WRKDIR
git add -A
for file in `git diff --cached -p --name-status | cut -c3-`; do
if [[ "$file" == *"$WHITELIST"* ]] ; then
echo "$file is on whitelist"
else
echo "$file is not on whitelist. Commit aborted."
exit 1
fi
done
The problem is, it's always uses the 'else' clause.
I can't find the problem. Thanks
As a best-practices approach, consider:
#!/usr/bin/env bash
# ^^^^ important: [[ ]] is not guaranteed to work with bin/sh
whitelist_re='(foo|bar)'
workdir=/home/athur/workwork/test/repo
cd -- "$workdir" || exit
git add -A
while IFS= read -r filename; do
if [[ $file =~ $whitelist ]]; then
echo "$file is on whitelist" >&2
else
echo "$file is not on whitelist; commit aborted." >&2
exit 1
fi
done < <(git diff --cached --name-only)
To walk through the changes:
The shebang specifies bash as a shell, which guarantees that extensions like [[ ]] and <(...) will be available -- a guarantee not made with /bin/sh.
A while read loop is used rather than attempting to iterate over line-oriented data with for; see DontReadLinesWithFor for an explanation of the reasoning behind this change.
The whitelist is specified as an ERE-compliant regular expression, such that =~ can be used to test whether a value matches.
Instead of using git diff --cached --name-status and then using cut to remove the status data after-the-fact, we use --name-only to generate only names in the first place.
Using lowercase variable names complies with the conventions given in http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap08.html, specifying that POSIX-defined tools will use all-caps shell and environment variable names for their own purposes, and that names with at least one lowercase character are reserved for application use. (Keep in mind that setting a shell variable overwrites any like-named environment variable, so these conventions apply even when export is not in use).
By the way, if you just wanted to find out if any non-matches exist, without knowing which files those are, you could use:
#!/bin/sh
# ^^ actually safe here, as no non-POSIX functionality is used
whitelist_re='foo|bar'
if git diff --cached --name-only | grep -qEv "$whitelist_re"; then
echo "At least one file is not on whitelist; commit aborted" >&2
exit 1
fi
Using an explicit list
The == is not symmetric in this case and ** seems to be used badly.
Try "$WHITELIST" == *"$file"*.
(Inspired by How do I check if a variable exists in a list in BASH)
Note that using your WHITELIST, only files foo and bar will be whitelisted.
Detecting a pattern
If you need to detect individual patterns, you may need to construct a function such as:
for entry in $WHITELIST ; do
if [[ "$file" =~ $entry ]] ; then
return 0
fi
done
return 1
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.