1

I wanted to check for changed files between previous commit occurs and latest commit with

git diff ${CI_COMMIT_BEFORE_SHA} ${CI_COMMIT_SHA} --name-only

For official documentation about

${CI_COMMIT_BEFORE_SHA} : The previous latest commit present on a branch. Is always 0000000000000000000000000000000000000000 in pipelines for merge requests.

So from my assumption, when there are some changes but no merge request occur, that ${CI_COMMIT_BEFORE_SHA} shouldn't be 0000000000000000000000000000000000000000. However, recently I've tested with this following .gitlab-ci.yml

stages:
  - info
  - deploy

variables:
  GIT_STRATEGY: fetch
  GIT_CHECKOUT: "true"

information:
  stage: info
  script:
    - echo ${CI_COMMIT_BRANCH}
    - echo ${CI_COMMIT_BEFORE_SHA}
    - echo ${CI_COMMIT_SHA}
    - export CHANGES=`git diff ${CI_COMMIT_BEFORE_SHA} ${CI_COMMIT_SHA} --name-only`
    - echo ${CHANGES}
  only:
    variables:
      - $CI_COMMIT_BRANCH == "test"
  tags:
    - master

Some scenarios

  1. Update .gitlab-ci.yml itself, the ${CI_COMMIT_BEFORE_SHA} was not equal all zero (correct)
  2. Create text file and add some contents via Gitlab UI Here's where the issue occurred
    • first edit: After running the pipeline ${CI_COMMIT_BEFORE_SHA} was not equal all zero (correct) and ${CI_COMMIT_SHA} was changed to a new number.
    • second edit: ${CI_COMMIT_BEFORE_SHA} was changed to all zero !? and ${CI_COMMIT_SHA} remain the same as the previous one.

from the second attempt, I just only added words in same text file, No merge occur. Why did the ${CI_COMMIT_BEFORE_SHA} behave like this? I also see this kind of behavior in other project. Isn't it weird? or it's my misunderstanding ?

Here's the output from Gitlab's runner panel

  1. First edit
Skipping Git submodules setup
Executing "step_script" stage of the job script
00:01
$ echo ${CI_COMMIT_BRANCH}
test
$ echo ${CI_COMMIT_BEFORE_SHA}
02c9b473c269ff69f54eac42fd5d1c4ace98888e
$ echo ${CI_COMMIT_SHA}
c3d04bd751d4199aa6f2a5c43f3da55100ce42a3
$ export CHANGES=`git diff ${CI_COMMIT_BEFORE_SHA} ${CI_COMMIT_SHA} --name-only`
$ echo ${CHANGES}
test.txt
Cleaning up file based variables
00:00
Job succeeded
  1. Second edit
Executing "step_script" stage of the job script
00:00
$ echo ${CI_COMMIT_BRANCH}
test
$ echo ${CI_COMMIT_BEFORE_SHA}
0000000000000000000000000000000000000000
$ echo ${CI_COMMIT_SHA}
62f73dcf2ae8672752fa1ace7a77b97d33ee49df
$ export CHANGES=`git diff ${CI_COMMIT_BEFORE_SHA} ${CI_COMMIT_SHA} --name-only`
fatal: bad object 0000000000000000000000000000000000000000
$ echo ${CHANGES}
Cleaning up file based variables
00:00
Job succeeded
BTH.S3
  • 199
  • 1
  • 3
  • 12

2 Answers2

3

If you look to the documentation page of variables: https://docs.gitlab.com/ee/ci/variables/predefined_variables.html

Then you will see that CI_COMMIT_BEFORE_SHA and CI_COMMIT_SHA are always 0000000000000000000000000000000000000000 in pipelines for merge requests.

That is probably the problem you are facing.

You can create your own variables:

export COMMIT_BEFORE_SHA="$(git rev-parse HEAD~1)"
export COMMIT_SHA="$(git rev-parse HEAD~0)"

So the example will look like:

stages:
  - info
  - deploy

variables:
  GIT_STRATEGY: fetch
  GIT_CHECKOUT: "true"

information:
  stage: info
  script:
    - export COMMIT_BEFORE_SHA="$(git rev-parse HEAD~1)"
    - export COMMIT_SHA="$(git rev-parse HEAD~0)"
    - echo "${COMMIT_BEFORE_SHA}"
    - echo "${COMMIT_SHA}"
    - export CHANGES="`git diff "${COMMIT_BEFORE_SHA}" "${COMMIT_SHA}" --name-only`"
    - echo "${CHANGES}"
  only:
    variables:
      - $CI_COMMIT_BRANCH == "test"
  tags:
    - master
kelvin
  • 1,421
  • 13
  • 28
  • 1
    `git rev-parse HEAD~1` will don't always be equal to `CI_COMMIT_BEFORE_SHA`, for instance when you push several commits at once – Gabriel Mar 24 '22 at 10:12
  • I have a case where `CI_PIPELINE_SOURCE` is `merge_request_event` and `CI_MERGE_REQUEST_EVENT_TYPE` is `merge_train`, but `CI_COMMIT_BEFORE_SHA` is populated with a nonzero SHA. Also `CI_COMMIT_BEFORE_SHA` and `CI_COMMIT_SHA` are equal. – solstice333 Apr 05 '23 at 19:50
3

From my own tests, I see CI_COMMIT_BEFORE_SHA be 0000000000000000000000000000000000000000 when I push a new branch (with CI_PIPELINE_SOURCE being push)

As of today (March 2022), the documentation does not list all the cases where CI_COMMIT_BEFORE_SHA== 0000000000000000000000000000000000000000

enter image description here

Gabriel
  • 3,633
  • 1
  • 23
  • 13
  • 5
    CI_COMMIT_BEFORE_SHA is also 0000000000000000000000000000000000000000 for push pipelines for tags (e.g. on the main branch) – BlackShift Jun 20 '22 at 10:40