j2emanue
j2emanue

Reputation: 62519

how to create shell script to check if two commits are equal

I have a small shell script I'm writing, but I can't get the syntax right. All it does is check if git is up to date by checking commit hashes using rev-parse.

So this: (git rev-parse HEAD) == $(git rev-parse @{u})

should tell me if i need to do a git pull or not. If both return the same number, then I know the commit hashes are the same, and I don't need to do anything. But now I'm trying to put this in a shell script, and I have issues. Here is what i have so far:

#!/bin/sh
export isNew = (git rev-parse HEAD) -eq $(git rev-parse @{u})

if [$isNew -eq 0]; then
echo "its new"
fi

But I get the following error :

$./myscript.sh
./myscript.sh: line 2: syntax error near unexpected token `('
./myscript.sh: line 2: `export isNew = (git rev-parse HEAD) -eq $(git rev-parse @{u})'

Upvotes: 0

Views: 927

Answers (3)

TerraPass
TerraPass

Reputation: 1602

#!/bin/sh

# Test for equality
[ $(git rev-parse HEAD) == $(git rev-parse @{u}) ]
# Assign result to a new variable (0 for true)
isNew=$?

# Then you can check isNew
if [ $isNew -eq 0 ]
then
    echo "its new"
fi

Square brackets are used to test the condition. Note that [ $(git rev-parse HEAD) == $(git rev-parse @{u}) ] by itself does not output anything but uses a return code to indicate its result. Therefore, instead of assigning bracketed expression to the variable directly, you need to use $?, which contains the return code of the last executed command and assign it to a new variable, if you want to keep it for later use.

For assignment to work, there must be no spaces around =, that's why you should write isNew=$? and not isNew = $?. Additionally, export is probably unnecessary in your case, if you only intend to use isNew in this script.

One more point, -eq tests for numerical equality. To test whether two strings are equal, you probably want ==.


EDIT

However, as for your intention to use this script to check whether you need to perform a pull, simply comparing HEAD to @{u} is not enough, since @{u} refers to the tip of your upstream branch, kept locally since the last time you did a git fetch and remote branch tip may well have changed since then, but you wouldn't know it just by checking @{u}.

Your script will not detect whether someone has pushed to the remote branch, unless you do a fetch to "refresh" your repository beforehand.

With this in mind, it might be better to do something like:

#!/bin/sh

# Fetch the remote branch, tracked by your current local branch.
# This will set FETCH_HEAD to the latest commit in remote branch
# without affecting your working copy.
git fetch
# Test for equality between HEAD and FETCH_HEAD
[ $(git rev-parse HEAD) == $(git rev-parse FETCH_HEAD) ]
# Assign result to a new variable (0 for true)
isNew=$?

# Then you can check isNew
if [ $isNew -eq 0 ]
then
    echo "its new"
fi

Upvotes: 1

torek
torek

Reputation: 487725

Others have addressed some of this; I'll first add something I like to use with shell variables that are later used for boolean tests.

Let's use your setup:

if [ $(git rev-parse HEAD) == $(git rev-parse @{u}) ]; then
    upstream_matches_HEAD=true
    # more code here as desired
else
    upstream_matches_HEAD=false
    # more code here if desired, again
fi
# whatever code here
if $upstream_matches_HEAD; then
    # still more code
fi

When setting the variable to true we end up running if true; then .... When setting it to false we end up running if false; then .... I find it reads nicely later as well, especially if you choose good variable names.

ahead, behind, or both

I noticed above (per comments) you may be concerned with who's "ahead" and/or "behind" (upstream vs current branch). Note that after doing git fetch, it's possible that you can be ahead, behind, or even both. For instance, suppose that on branch develop you've made 3 commits that you have not pushed ... but a co-worker has made 2 commits that she has pushed. You're now "3 ahead, 2 behind" in git status terms.

To get these values, use git rev-list --count on HEAD-vs-@{u}:

# find out how many un-pushed commits we have,
# i.e., commits that are on HEAD but not on the upstream
ahead=$(git rev-list --count @{u}..HEAD)

# same for un-merged un-rebased-onto commits: what is
# on the upstream that we don't have?
behind=$(git rev-list --count HEAD..@{u})

(You can omit the word HEAD from these, although I think it reads a bit better to keep it.)

Upvotes: 1

LinuxDisciple
LinuxDisciple

Reputation: 2379

Were you going for something like this?

if [ $(git rev-parse HEAD) == $(git rev-parse @{u}) ] ; then
    echo "It's different"
fi

Linux:
There's no need for 'export' there.
You can't use '-eq' alone and save its result.
Note the space after '[' and the space before ']', they're necessary.


Git:
The sums not matching doesn't imply which one's ahead.

Upvotes: 0

Related Questions