I have a CI/CD pipeline in GitHub Actions that runs and one of the steps is to commit to another repository. What it does is that it clones to external repository, moves files into it, and then commits it back to the external repository.
The thing is, there is no grantee that there will be a new file to commit.
When that happens, the repository fails because Git throws an error as shown
How can I get around that?
You could use the git status --porcelain command (reference 1 + reference 2) to check if some changes occurred.
It could look like this using bash:
run:
if [[ `git status --porcelain` ]]; then
echo "OK: Changes detected."
else
echo "WARNING: No changes were detected."
fi
shell: bash
Obs: I'm using it in a action to git commit push changes.
Related
I have a script.sh that performs the "clone" operation of a git repository. Currently, the script works correctly with the target branch written in hard on the corresponding line.
/usr/bin/git clone https://my-url-repository --branch master --single-branch
If I replace "master" with "$1",
/usr/bin/git clone https://my-url-repository --branch $1 --single-branch
it can't complete the operation because it doesn't correctly take the branch and throws a fatal error.
warning: Could not find remote branch e to clone.
fatal: Remote branch e not found in upstream origin
However, if I print on screen the parameter $1 or ${1}, the entered value is displayed correctly.
#!/bin/bash
if [ -n "$1" ]; then
echo Building from branch "["$1"]"
else
echo "Please, enter branch name"
exit
fi
Can you help me?
I could not specifically solve the problem, but I did find an equally valid alternative. Instead of waiting for the parameter in the script call, within the same script I request the entry of the branch name, and then the clone is done without problems.
The code looks like this:
#!/bin/bash
echo "Please, enter branch name"
read branchName
And then I use the variable like this:
/usr/bin/git clone https://my-url-repository --branch $branchName --single-branch
After merging one branch into another, (like develop into master) with
git merge --no-ff develop
If you execute the git command git status in a terminal just after you will see:
On branch master
Your branch is ahead of 'origin/master' by 1 commits.
(use "git push" to publish your local commit)
nothing to commit, working tree clean
Which is not much different from that (if we look without paying attention):
On branch master
nothing to commit, working tree clean
Sometimes I do not pay much attention and I forget to push. So is there an command to know if we must push? or a way to color the Your branch is ahead of 'origin/master' by 1 commits. part in red?
or may be just a command that return 0 or 1 if we need to push, if yes I could include it with an echo routine in a git alias to make my git status more explicit.
Finally, I resolved it by putting this in my ~/.gitconfig:
[alias]
st = "!f() { git status -u; \
git status -u | grep \"Your branch is ahead\" > /dev/null \
&& echo \"\\e[31m[WARNING]\\e[91m You need to push :)\"; }; f"
Like that just by performing git st I will be warned by a red message if I need to push.
When working with many projects and branches at the same time, I occasionally do stupid mistake like pulling into the wrong branch. For example being on branch master I did git pull origin dangerous_code and didn't notice that for quite some time. This small mistake caused a lot of mess.
Is there any way to make git ask for confirmation when I attempt to pull a branch other than branch that is currently checked out? Basically I want it to ask for confirmation if the branch name doesn't match (checked out and the one being pulled).
For now, I'll focus on how to prompt the user for confirmation before any pull is carried out.
Unfortunately, because there is no such thing as a pre-pull hook, I don't think you can get the actual pull command to directly do that for you. As I see it, you have two options:
1 - Use fetch then merge (instead of pull)
Instead of running git pull, run git fetch, then git merge or git rebase; breaking down pull into the two steps it naturally consists of will force you to double-check what you're about to merge/rebase into what.
2 - Define an alias that asks for confirmation before a pull
Define and use a pull wrapper (as a Git alias) that prompts you for confirmation if you attempt to pull from a remote branch whose name is different from the current local branch.
Write the following lines to a script file called git-cpull.sh (for confirm, then pull) in ~/bin/:
#!/bin/sh
# git-cpull.sh
if [ "$2" != "$(git symbolic-ref --short HEAD)" ]
then
while true; do
read -p "Are you sure about this pull?" yn
case "$yn" in
[Yy]*)
git pull $#;
break
;;
[Nn]*)
exit
;;
*)
printf %s\\n "Please answer yes or no."
esac
done
else
git pull $#
fi
Then define the alias:
git config --global alias.cpull '!sh git-cpull.sh'
After that, if, for example, you run
git cpull origin master
but the current branch is not master, you'll be asked for confirmation before any pull is actually carried out.
Example
$ git branch
* master
$ git cpull origin foobar
Are you sure about this pull?n
$ git cpull origin master
From https://github.com/git/git
* branch master -> FETCH_HEAD
Already up-to-date.
Is there any way to block deletion of remote branches?
I want to block deletion of remote branches but normal flow like code checking and check out should work fine!!
without using gitolite! is it possible ?
please help !
Yes, it is possible. Just add a suitable server side git hook.
You probably want to use a pre-receive hook. For details have a look at here or here.
Example:
#create repositories
git init a
git init --bare b
#add the hook in "b"
echo -e '#!/usr/bin/bash\nread old new ref\ntest $new != 0000000000000000000000000000000000000000' >>b/hooks/pre-receive
chmod +x b/hooks/pre-receive
#create a commit in "a"
cd a
echo foo >test
git add .
git commit -m testcommit
#push it to "b"
git push ../b master
#try to delete remote branch
git push ../b :master
refs/heads/*,delete)
# delete branch
if [ "$allowdeletebranch" != "true" ]; then
echo "*** Deleting a branch is not allowed in this repository" >&2
exit 1
fi
adding this in update hook solved my problem
Hope this will help someone else too
I'm not sure why you're avoiding gitolite (which is sort of the end point of all access control, as it were), but I have a sample pre-receive script here that uses hooks.* git config entries to do some simple access controls. It's not as fancy as gitolite but it does some things I cared about once. :-)
I have embedded Linux system that we want to store in Git. I have installed Git on the system, mount additional USB drive for storing Git data (bare repository). There is no problem with committing and pushing to the remote repository using commands like that:
cd /media/usb
git init --bare
git --work-tree=/ add -A
git --work-tree=/ commit
git --work-tree=/ push -u origin master
But when I clone bare repository to new USB drive and invoke git --work-tree=/ status I see all previously pushed files as deleted, and untracked. How to tell Git to use the work-tree?
The reason you are seeing previously committed files as deleted is that the git index (which is simply a file called index) in the first repository differs from the index in the second repository. The index in the first corresponds to the working tree, whereas the index in the second is uninitialized and therefore has no entries. The output from git status is the result of two comparisons:
between HEAD and the index (to determine staged changes to be committed)
between the index and the working tree (to determine unstaged changes which will not be committed)
In your case, HEAD in the second repository points to a commit which contains all the files you committed from your root filesystem, but the index is empty. So when git performs the first comparison, it thinks that each of these files has been staged for deletion on the next commit.
When git performs the second comparison, it finds that the working tree contains all the same files as the commit, but the index is of course still empty, so it sees these files as "new" untracked files. That is why you see all the files as both deleted and untracked.
The solution is very simple: initialize the second index so that it matches master:
git --work-tree=/ reset
While I'm here, I should point out some other issues with the commands you posted:
Firstly, your git add -U is adding all the git repository meta-data files to the repository. In other words, the repository is tracking itself. This is happening as a consequence of the way you use --work-tree, and is very bad. You should ensure that the repository files are ignored by adding them to info/exclude or .gitignore.
Secondly, you don't really want a bare repository here, just a detached working tree. You could have achieved this via git config core.bare false and export GIT_DIR=/media/usb; then you could run git commands from outside (i.e. above /media/usb), and you wouldn't have to continually include --work-tree=/ as a global option in each command.
Here's a complete test case which encapsulates everything I just covered except for the second bullet point:
#!/bin/sh
root=fakeroot
mkdir -p $root/media/usb{1,2} $root/{bin,etc}
echo a > $root/bin/sh
echo b > $root/etc/hosts
cd $root/media/usb1
git init --bare
# We don't want our git repository meta-data being tracked.
echo '/media/usb*/' >> info/exclude
git --work-tree=../.. add -A ../..
git --work-tree=../.. commit -m '1st commit'
echo c >> ../../etc/hosts
git --work-tree=../.. add -A ../..
git --work-tree=../.. commit -m '2nd commit'
git remote add origin ../usb2
git --git-dir=../usb2 init --bare
git push origin master
cd ../usb2
echo '/media/usb*/' >> info/exclude
echo "========================================="
echo "index in usb2 is not yet initialized:"
git --work-tree=../.. status
echo "========================================="
echo "initialize index to master (HEAD)"
git --work-tree=../.. reset
echo "========================================="
echo "now we have a clean working tree:"
git --work-tree=../.. status