Search code examples
gitgit-pull

Don't clone newer tags in a repository


I have a lot of repositories cloned, so I've made a script that checks if the expected tag is the same as the one I have. If not, it will git pull origin newtag. But sometimes the expected tag is older than the last tag in the remote, even though there isn't any change between both tags (but the new tag was created because other repos received changes). But with that git pull, I'm getting the newest tag, and not the expected one. So the script will git pull origin newtag again, even though I already have it. To check the current tag I'm in I use git describe --tags --exact-match


Solution

  • TL;DR: just don't fetch again

    If you avoid fetching, you'll avoid picking up new names for existing commits. If that's not suitable you will just have to save the tag name yourself somewhere. If you find a new tag, you can detect that it points to the same commit by using git rev-parse:

    git rev-parse android-8.0.0_r4^{commit}
    git rev-parse android-8.0.0_r12^{commit}
    

    would produce the same hash here.

    Long description

    Tags don't necessarily have ages—Git's "annotated tags" do have a timestamp but lightweight tags just add a new name for an existing commit and have no timestamp of their own—and even if they do, a single linear measure rarely suffices when dealing with branching.

    git clone -b android-8.0.0_r4 https://android.googlesource.com/platform/build/blueprint

    In your particular example, if we go look at https://android.googlesource.com/platform/build/blueprint, we find that tags 8.0.0_r4 and 8.0.0_r12 are annotated tags, but literally point to the same commit, 4fcacd3d193f1e1dfb0f5a9e818dd895eca45427.

    The tag 8.0.0_r11 also points to this same commit (click on https://android.googlesource.com/platform/build/blueprint/+/android-8.0.0_r11 to see; change r11 to r4 or r8 to see each annotated tag in their chosen web-page-display-format).

    In other words, it doesn't matter which of these tags you check out: you get the same source code for all three of them. If you want to remember which tag you used to do the git checkout operation—the final step of the git clone in your example—you must save it yourself somewhere. Git saves, instead, the fact that this checked out commit 4fcacd3d193f1e1dfb0f5a9e818dd895eca45427, and git describe --tags looks for a tag that leads to 4fcacd3d193f1e1dfb0f5a9e818dd895eca45427. It finds many, and picks one. Here, it does use the annotated tag date if it's looking at annotated tags.

    Whenever you run git fetch (the first half of git pull), Git obtains new objects; that may include new tags. The main way to avoid picking up new tags (of any type, lightweight or annotated) is to avoid fetching.

    If it's too late to avoid picking up new tags, note that you can look at all the tags (or all the annotated tags) by using git for-each-ref refs/tags and resolving each tag to its target object (usually a commit), or specifically to a commit (which fails if the tag points to some other object type, after perhaps following it through previous tags).