4

I am running a ci task on my Gitlab server. One of the actions is to call an exe on the build runner machine which does some updates.

I pass through the SHA1s from $CI_COMMIT_BEFORE_SHA and $CI_COMMIT_SHA and the code calls:

git diff --name-only $CI_COMMIT_BEFORE_SHA $CI_COMMIT_SHA

Usually it gives me a list of file names which have changed in the commit but sometimes I get the error:

fatal: bad object abcd1234
                  ^
                  |-- This is the $CI_COMMIT_SHA

The repo has just been downloaded to the build runner so it is up to date, why would the git diff return a bad object here?

Gaël J
  • 11,274
  • 4
  • 17
  • 32
Stefan
  • 3,669
  • 2
  • 32
  • 43
  • 1
    What runner are you using? Do you need to research difference between powershell and Linux shell? – KamilCuk May 19 '21 at 16:46
  • 1
    According to https://stackoverflow.com/a/20264177/3216427, that message means the repository is corrupt. Do you get other strange file system issues in that setup? Do you see any other error messages from previous Git commands in the CI recipe? – joanis May 19 '21 at 17:49
  • 1
    I'm not sure the solutions there would be of any help, but https://stackoverflow.com/a/60971746/3216427 says doing an extra `git fetch origin` helped them. It's all a bit mysterious to me how a Git sandbox gets corrupted in the first place, unless something is unstable in the environment. – joanis May 19 '21 at 17:54
  • 3
    To clarify, does the error actually output `fatal: bad object $CI_COMMIT_SHA` with the variable not replaced or is the variable replaced? – Gaël J May 19 '21 at 19:29
  • @KamilCuk, the problem is that is usually works. The runner is no different between runs that work and ones which do not – Stefan May 20 '21 at 08:34
  • @joanis, no - everything else is fine. – Stefan May 20 '21 at 08:35
  • @joanis, I tried the git fetch and then git diff and it worked when I did it by hand but did not seem to fix the issue when used in the runner – Stefan May 20 '21 at 08:35
  • 1
    @GaëlJ, it is with the variable replaced with the actual value – Stefan May 20 '21 at 08:36
  • Can you add `git fsck` to your build recipe, and see if the output provides any clues? – joanis May 20 '21 at 17:22

2 Answers2

4

If the commit is "old" it could be missing from the clone because Gitlab uses a shallow clone with a depth of 20 by default.

This is why you see this message in the job's log:

Fetching changes with git depth set to 20...

Possible solutions:

  • use the web interface to increase this value for your project (or disable shallow cloning).
  • override variable GIT_DEPTH from .gitlab-ci.yml
  • re-clone the repo manually using a standard clone inside its .gitlab-ci.yml scripts
  • stop relying on "old" hashes
Gabriel Devillers
  • 3,155
  • 2
  • 30
  • 53
  • 1
    The note about 'shallow clone' was key to helping me solve a similar problem with Azure DevOps pipelines using `git diff-tree...`. After I disabled shallow clone in the pipeline definition, then the git statement would work. Snippet of YAML `- checkout: self clean: true fetchDepth: 0`. – Stringfellow Jan 21 '23 at 20:23
1

git fetch origin $CI_MERGE_REQUEST_TARGET_BRANCH_NAME git diff-tree --no-commit-id --name-only -r $CI_COMMIT_BEFORE_SHA -r $CI_COMMIT_SHA

It helped me!

Faik91
  • 11
  • 2
  • Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Apr 05 '22 at 08:53