Re: Difficulties of scripting git
- From
brian m. carlson <sandals@crustytoothpaste.net>
- Date
- Jan 9, 2021, 21:42 UTC
- Message-ID
- <X/ojXdtGOHeP2IhY@camp.crustytoothpaste.net>
- In-Reply-To
- <X/oAhdZlLwcFRCrR@ACM>
On 2021-01-09 at 19:14:13, Alan Mackenzie wrote:
Show 25 quoted lines
> Hello, git. > > I want to write a bash script (more precisely, correct an existing > script) which uses git, and it is DIFFICULT!!! > > I need a git pull in the script. Fine, but how does the script know if > it's worked or not? I couldn't find any description of a return code in > the git-pull man page (or in the git-merge man page). > > The big problem is when I have modified, uncommitted files in the target > repo, and those same files are to be updated in commits coming from the > source repo. Sadly, git is unable to merge these changes. It just > fails, putting an error message onto stderr, but doesn't tell the > calling script in any way that I can see. > > One idea would be always to call git stash before doing the pull, then > git stash pop afterwards. Trouble is, git stash is unreliable - it > doesn't always add a new stash entry, so the stash pop at the end would > sometimes/often pop off an entry it shouldn't. git stash doesn't have a > --force argument. git stash doesn't set a result code, either, that I > can see. One way around this would be to do > > $ git stash list | wc -l > > both before and after the git stash and compare the answers, but really?
git stash doesn't consider there being nothing to stash to be an error, so it doesn't set a nonzero error code. Think of it as, "I want a clean working tree," not, "I want to create a stash." In that sense, what you wanted is already done, so it's not an error.
You are, however, not the only person who's been unhappy with this behavior. A --force option may be a useful option to have if someone wanted to create it.
Show 5 quoted lines
> So, next idea, feed the output from git status --porcelain through grep > before and after the git pull, so as to find out whether there are any > modified files before the git pull (thus making a stash necessary) and > any files with conflicts after the git stash pop. Shouldn't be too > difficult.
Using "git status --porcelain" before and after the stash is an easy way to find out whether there was anything to stash. If there's a difference, then a stash was created.
Show 13 quoted lines
> Except, how does one recognise a file with conflicts from this git > status output? The man page says that > > " For paths with merge conflicts, `X' and `Y' show the modification > states of each side of the merge. For paths that do not have merge > conflicts, `X' shows the status of the index, and `Y' shows the status > of the work tree. For untracked paths, `XY' are `??'. Other status > codes can be interpreted as follows: ...." > > I've spent nearly an hour trying to make sense of this bit of man page. > How is one meant to distinguish an XY of a merge conflict from the XY of > an index/work tree entry? I can't find that key bit of information > anywhere.
In the chart, the options in the first section are "normal" cases that occur without a merge conflict. The second section is things that happen when there's a conflict (the "unmerged" states).
So what you're looking for to find conflicts is something maybe a little like this:
git status --porcelain | grep -E '^(AA|DD|[AUD]U|U[AUD])'
If you believe that you're likely to need to handle names with newlines, then of course you'll need -z as well.
I do agree that this is a little unclear; I went ahead and simulated a merge conflict to verify. I'll try to send a patch making the documentation reflect what I mentioned about the chart above.
-- brian m. carlson (he/him or they/them) Houston, Texas, US