I have a script that auto merges a feature branch into master. It runs periodically.
I want the script to check that the feature branch does in fact have commits to be merged. If there are no commits the script should exit.
I’ve tried the following:
git rev-list --count HEAD
Run while on the feature branch called ‘test’ with no commits this is returning a value of 1, so the script doesn’t exit, even though it should because there are no commits to merge.
Note that I ran git fetch —all before all of these commands.
Also tried the following:
Tried:
git rev-list --count master..
Resulted in error:
fatal: ambiguous argument 'master..': unknown revision or path not in the working tree.
Tried:
git rev-list --count master
Resulted in error:
fatal: ambiguous argument 'master': unknown revision or path not in the working tree.
Tried:
git rev-list --count master..test
Resulted in error:
fatal: ambiguous argument 'master..test': unknown revision or path not in the working tree.
How do I determine (from a script) if there are commits to merge?
The command you are using is absolutely correct. The error you are seeing in your case means that master as a branch is not available in the local file system of the repository from where you are running this command.
To make this work properly, you'd want to put in the right reference.
git rev-list --count origin/master
Assuming that the remote you want to check against, is named origin.
Additionally you can do some shell magic to make it work like you want, the below works with zsh:
# merge branch
commit_distance=$(git rev-list --count origin/master)
if [ $commit_distance -eq 0 ];
then
exit 1
fi
# ... the remaining script
Related
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.
I have a Git pre-commit hook, which fetches local branch name and add checks with my pre defined Regex and alerts developer to if not matching.
I am finding the local branch name using
local_branch="$(git rev-parse --abbrev-ref HEAD)"
It is working good during normal commit process.
But in case, if I did a wrong commit message and I will edit it using the option "Rebase childern of abc interactively" in soucetree and edit the message. At this time my match condition on regex is failing as the local branch is not coming as expected.
In happy case it is coming as origin/feature/XYZ-01
but while editing message it is coming as just "HEAD"
Tried using git branch --show-current and its giving nothing.
Also tried, git branch | sed -n '/\* /s///p' and its giving "no branch, rebasing feature/XYZ-01"
Is there a way that I can get current branch in all cases like regular/Rebase etc.
How to get local branch name during rebase and what other cases also should I need to consider?
Suppose I have a git repo at ~/dev/company/products/company-common. From several other filesystem location I try to execute ls-files or ls-remote on that repo. All work, except for the last one. What could be a reason the last one doesn't work?
(N.B. I have a 2-line bash prompt):
user#machine:products (~/dev/company/products)
$ git ls-remote company-common HEAD
f25b342b384de1b82cb67b6f530303b4fac37ff0 HEAD
user#machine:products (~/dev/company/products)
$ git ls-remote ../products/company-common HEAD
f25b342b384de1b82cb67b6f530303b4fac37ff0 HEAD
user#machine:products (~/dev/company/products)
$ git ls-remote ../../company/products/company-common HEAD
f25b342b384de1b82cb67b6f530303b4fac37ff0 HEAD
user#machine:products (~/dev/company/products)
$ cd gui
user#machine:gui [master] (~/dev/company/products/gui)
$ git ls-remote ../company-common HEAD
f25b342b384de1b82cb67b6f530303b4fac37ff0 HEAD
user#machine:gui [master] (~/dev/company/products/gui)
$ cd dummy/
user#machine:dummy-application [master] (~/dev/company/products/gui/dummy)
$ git ls-remote ../../company-common HEAD
fatal: '../../company-common' does not appear to be a git repository
fatal: Could not read from remote repository.
Please make sure you have the correct access rights
and the repository exists.
None of the directories involved is a symlink. I've only shown one line of output from each command (except for the last one)
The interesting thing is that git ls-remote works at all here.
The first argument you pass to git ls-remote should be a URL (https://host/..., ssh://git#github.com/..., and so on) or the name of a remote (typically origin). However, Git accepts local file system paths in place of file://... URLs.
When Git does that last trick, it seems to do it somewhat weirdly and inconsistently. In my experiments I got somewhat different behavior, but it was still weird.
Aside from academic curiosity and/or possible internal bugs, you should just stop using git ls-remote here and use git rev-parse directly. If you want to get a revision hash ID from the current repository, just run git rev-parse:
git rev-parse HEAD
for instance. If you want to get one from some other Git repository in file system location X, use:
git -C X rev-parse HEAD
for instance. This behaves well—unlike the odd results you and I are seeing for git ls-remote here, the -C argument makes Git internally chdir for the duration of the rev-parse—and runs faster and is simpler and easier to deal with. It works for git ls-files and all other Git commands too, since it is implemented in the git front end.
Simple git question. After executing:
git reset HEAD file && git checkout -- file
The file is still under "Changes not staged for commit" section, but it shouldn't. If I execute the two operations seperately (ie. pressing enter and seeing git status between and after them), it works.
Platform: Linux amd64, git version 1.8.1.3
This is because git reset returns a non-zero exit code when the file has unstaged commits after the reset. So the && prevents the git checkout from running -- it will only run the second command if the first "succeeds" (i.e. exits with zero).
git reset HEAD file just updates the index (i.e., any staged changes to the file are lost), the changed file stays as is.
Why do it this way, if a simple git checkout file (perhaps with -f if file has been changed) acomplishes the same?
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