5

How can use merge-base with Git on a remote repository without checking it out? Using ls-remote works fine e.g. for determining branches like this:

git ls-remote --heads $REPO_URL/$REPO_NAME

The documentation contains no clue, wether the use of merge-base with ls-remote is possible. Maybe it is also possible, to use alternatives to merge-base to find the common ancestor for branches/commits.

At the moment, i have to checkout the repository locally, which takes a lot of time for big projects.

alex
  • 5,516
  • 2
  • 36
  • 60
  • 1
    Note that you do not need to check out locally, only clone. Use `git clone --no-checkout ...` to avoid the checkout. – sleske Jul 28 '14 at 07:40
  • 1
    Ok, thats nice, but my proplem remains that i have to clone the repository and this takes a lot of time. Maybe there is also a way, just to clone the `Git` meta information or something like that... – alex Jul 28 '14 at 07:50
  • You would need, at a minimum, all the commit objects going back to the merge base, and possibly annotated tags in various cases. You could omit regular files and trees, which would save space. But it's a heck of a lot easier to keep a full clone (or an initial shallow one, if you prefer) and just update it as needed with `git fetch`. – torek Jul 28 '14 at 07:58

1 Answers1

3

In general, no: ls-remote shows you the commit IDs on the remote for the requested references, but for each commit-ID, if you do not have that commit locally you cannot determine its parent commit(s).

There is no need to check out the commits though. Just use git fetch to bring over any missing objects, and you will then have the full repository history. A future git fetch will continue to bring over only missing objects, which will be new objects that you would need anyway in order to find items.

I do not know what you are attempting to do with git merge-base but it requires only commit-IDs for all but the new --fork-point operation, where it uses your local reflog and therefore requires a local reference-name. For instance:

$ git merge-base 9b1c2a3a8e625ea7f56e9ba3d3c0e31938faa738 \
> bba6acb335e296ed692b4aea224b50fd098f693c
ebc5da3208824e25a89672a3b91bd13629b215fe

This tells me that the merge-base of 9b1c2a... and bba6acb... is ebc5da3.... (All of these are commit IDs within the repository containing the source to git itself.) And:

$ git branch -a --contains ebc5da3208824e25a89672a3b91bd13629b215fe
* master
  remotes/origin/maint
  remotes/origin/master
  remotes/origin/next
  remotes/origin/pu

tells us that the merge-base is contained within four remote branches: maint, master, next, and pu, plus the local branch master (which is in sync with origin/master anyway). More interestingly:

$ git describe ebc5da3208824e25a89672a3b91bd13629b215fe
v2.0.2

tells us that the merge-base is tagged as git version 2.0.2, so these two other commits (chosen arbitrarily out of the log) have common ancestry at that particular tag.

torek
  • 448,244
  • 59
  • 642
  • 775
  • 1
    Ok, thats helpful. `Git-fetch` is not usable for me, because the repository gets cloned, a merge-base gets determined and then the local repository becomes deleted again. The use case is to offer an webbased ui to determine a common ancestor for specific branches to split from, when creating a new branch. No the developer has to wait for `Git` to clone the repository and run `merge-base` for specific branches. Thats ok but not optimal. Keeping the repository and just fetch each time is no option, since we just have temporary files, that can be delteted at any time... – alex Jul 28 '14 at 08:10
  • @alex: In that case you will probably need to arrange for the web UI to run on the git server (or get direct read-only access to the server's repositories). Then it can use the repos directly without cloning. – sleske Jul 28 '14 at 08:15
  • @sleske's method would work well. Alternatively, you could cache repos: if you do not already have repo-x, clone it (preferably as a mirror), else `fetch` to update it. When the cache is over-large, prune least-recently-used repos. – torek Jul 28 '14 at 08:20
  • @Sleske That was also an idea, but now its done with cloning temporary each time, a developer needs to find an common ancestor. Since a clone takes approx. 20 seconds, its close to a smooth usage, but in future i might try to move to the `Git` repository server. Thanks for your help! – alex Jul 28 '14 at 08:20
  • @torek Caching would also be a solution. I think about that, thanks! – alex Jul 28 '14 at 08:27
  • You could also manage the fetching of history with 'git clone --depth' and 'git fetch --depth' and only ask for as much as the user is willing to handle in terms of wait time. But that kind of implies the client side would need to manage a windowing system, or at least "partial" vs. "full" history modes. – qneill Oct 18 '17 at 17:48
  • I wonder if github has this capability served somehow to do these remote ancestry checks. That would be awesome. – jxramos Feb 27 '23 at 23:09