0

I have written a script that clones a repo, creates a new branch, performs some changes, and pushes the changes. I am unsure what will happen in case of an error during branch creation. Because if there is some failure there is a possibility that the changes can get commit to the default branch. Here is an MRE of the script:

while read REPO
   do
      git clone {repo-url}
      cd $REPO
      if [ -d "$REPO-test" ]; then
        git checkout -b $BRANCH
          $command  // This command makes changes to some files in the repository. It actually creates a new file
          git add $file
          git commit ...
          git push ....
      fi
    done < $REPOS

I thought of using the exit code to test like:

if [ $? -eq 0 ] 
then 
  echo "Success" 
else 
  echo "Failure"
fi

So do this right after the git checkout -b $BRANCH and don't proceed further in case of error / the else clause.

I am not sure if that will make it error-proof or if there is a better way to achieve this in shell script or better commands to use in git

tripleee
  • 175,061
  • 34
  • 275
  • 318
nick
  • 107
  • 6
  • 2
    Just like almost all other *nix tools `git` will have a non-zero exit status whenever a command can't finish normally. So `git checkout -b $BRANCH || exit 1` would work. Or use [`set -e` (with all its caveats)](https://stackoverflow.com/questions/19622198/what-does-set-e-mean-in-a-bash-script). – Joachim Sauer May 04 '23 at 14:48
  • 2
    That's broadly speaking the right idea, but see [Why is testing “$?” to see if a command succeeded or not, an anti-pattern?](https://stackoverflow.com/questions/36313216/why-is-testing-to-see-if-a-command-succeeded-or-not-an-anti-pattern) - you want `git checkout -b blah || exit` to abort if the command fails. (Or, more broadly, explore `set -e`; but understand that this requires a whole different discipline around possible errors. See https://stackoverflow.com/questions/19622198/what-does-set-e-mean-in-a-bash-script) – tripleee May 04 '23 at 14:50
  • @JoachimSauer ninja'd me, but I hope my comment helps spell things out in more detail. – tripleee May 04 '23 at 14:51
  • You could maybe look at how the shell scripts are structured in the Git project. They seem to like doing things like chaining with `&&`. [link](https://github.com/git/git/blob/69c786637d7a7fe3b2b8f7d989af095f5f49c3a8/t/t1020-subdirectory.sh) – Guildenstern May 04 '23 at 15:56
  • I would test for the success of the checkout by doing `if git checkout -b $BRANCH; then ...`. And if you run bash (you tagged the question with both _bash_ and _zsh_, which is a bad idea anyay), doublequote your variables if there is the possibility that they contain spaces (I don't know whether spaces are allowed in git branch names, but `file` most likely **can** contain a space). – user1934428 May 04 '23 at 16:06
  • 1
    Do not `echo success` or `echo failure`. (If you do `echo failure`, make sure you do `echo failure >&2`, but don't do either). Let the command emit the error message. Just do `cmd || exit 1`, or `git add "$file" && git commit ... && git push ...`. – William Pursell May 04 '23 at 21:12

1 Answers1

1
if [ $? -eq 0 ] then echo "Success"; else echo "Failure"; fi

after each command or git will give you an overview of what went wrong (or right). It will not stop you from executing the rest of the commands.

The problem with using $? is, that you must make sure that the last command is really always the git. That may seem trivial, but when others maintain your script, or you need to change something after a year, it is a cause of errors.

In general, I would

if git add "$file" ; then
    echo "Added $file to git"
else
    # do some repair actions or bail-out with
    exit 1
fi

This gives you more flexibility to repair common problems than just

git checkout -b "$BRANCH" || exit 1
Ljm Dullaart
  • 4,273
  • 2
  • 14
  • 31
  • I don't think anyone is arguing against an explicit `if` structure if you need more complex handling of failures than one or two commands after `||`. The question doesn't reveal what exactly should happen if the `git` command fails; both constructs have their uses. – tripleee May 04 '23 at 17:16
  • For the record, `git checkout -b blah || { echo "$0: bailing out" >&2; exit 1; }` is a reasonably common idiom if you want to use the short-circuit `||` but need more than one command there. – tripleee May 04 '23 at 17:18
  • I have always been against one-liners, especially if the script needs to be maintained by others. – Ljm Dullaart May 04 '23 at 21:02
  • 1
    But `if command; then : nothing; else exit; fi` is a _lot_ clunkier than `command || exit` for correctly returning the failure exit code from `command` to the caller. You have to understand both idioms anyway. – tripleee May 05 '23 at 03:36