1

For CI jobs that need to work on the diff on an MR, I would like to fetch the source branch and target branch with enough history to reliably run something like git diff main...mr (where main is the target branch and mr is the source branch). (I.e., the history should include mr and go back far enough to find the merge-base.)

An unreliable and inefficient way to do this is to pick a depth that's likely to be enough (say 1024), and git fetch --depth=1024 mr && git fetch --depth=1024 main, but for extreme edge cases 1024 may not be enough, and in the normal case it fetches way more history than necessary.

We are using GitLab CI, so if there's no generic way to fetch up to a merge-base in git, any GitLab-specific solutions are welcome too.

As specific example, clang-tidy-diff is one of the tools I want to use that requires the diff.

aij
  • 5,903
  • 3
  • 37
  • 41
  • Provide more ref-issue https://stackoverflow.com/questions/27059840/how-to-fetch-enough-commits-to-do-a-merge-in-a-shallow-clone – Wei Mar 14 '22 at 02:19

1 Answers1

3

I don't know of a nice way to query the remote server "can you please tell me the merge base of those two branches ?", perhaps someone will come up with a better answer.

One way could be to fetch deeper and deeper as long as git merge-base mr main returns an error :

#/bin/bash

while ! git merge-base origin/mr origin/main > /dev/null; do
  depth=$((depth+1024))
  git fetch --depth=$depth origin mr && git fetch --depth=$depth origin main
done

In the odd case where you would allow completely unrelated branches to land in your central repo, you may want to also check if "fetching deeper" fetches something new.

LeGEC
  • 46,477
  • 5
  • 57
  • 104
  • I don't know if GitLab offer an API by which one might obtain the commit hash ID of the merge base. You might need more than that to work within the shallow clone, though: `--depth` or `--deepen` needs a numeric value, and `--shallow-since` needs a timestamp. Some versions of `git fetch` have `--shallow-exclude`, but the documentation mentions specifically branch and tag names here, so rev ID might not suffice. – torek Sep 09 '21 at 18:23
  • In any case, the OP should note that repeated fetching to deepen is likely the only available solution, and it's kind of expensive: you'll want to weigh the cost of repeated fetch vs the benefit obtained by limiting the depth. – torek Sep 09 '21 at 18:24
  • Yup, I was also considering repeated fetching with `--deepen` but assumed it would be expensive. Even if it reduces overall bandwidth, it would result in even more requests on the server. I was hoping there would be some fancy `refspec` or other option I didn't know about. – aij Sep 13 '21 at 18:44
  • 1
    Note: Implementers rote copying will create a dangerous code that infinitely loops if merge-base is failing for some other reason ;-) – antak Aug 01 '22 at 09:33