1

I have three branches: dev, staging and master. When I do git describe the result is v0.1 no matter which branch is checked out.

Following I will describe a workflow of making changed to dev adding a version tag and merging to staging and to master this new version.

  1. git checkout dev
  2. make some changes
  3. git add --all && git commit -m 'just some testing'
  4. git tag -a v0.19.0
  5. git push && git push --tags
  6. git checkout staging
  7. git merge dev
  8. git push
  9. git checkout master
  10. git merge staging
  11. git push

And now I run describe on every branch:

- git checkout dev && git describe && git describe --abbrev=0

Result:

v0.19.0-1-ge147b2d
v0.19.0

What I expected:

v0.19.0-1-ge147b2d
v0.19.0
  • git checkout staging && git describe && git describe --abbrev=0

Result:

v0.17.0-3-g684216f
v0.17.0

What I expected:

v0.19.0-xxxxx
v0.19.0
  • git checkout master && git describe && git describe --abbrev=0

Result:

v0.17.0-16-g99c19c9
v0.17.0

What I expected:

v0.19.0-xxxxx
v0.19.0

enter image description here

Why is that? And how can I have such a process where I make some changes in dev then add a new tag and then propagate those changes with the tag to all the other branches?

zlZimon
  • 2,334
  • 4
  • 21
  • 51
  • 1
    Have you tried the [documented heuristics approach](https://git-scm.com/docs/git-describe#_search_strategy), executing `git log TAG1..HEAD` and `git log TAG2..HEAD`, and see what the results are? – Lasse V. Karlsen Apr 21 '21 at 08:47
  • Given that `TAG1` is the most recent one then `git log TAG1..HEAD` gives me every merge commit from dev where I added a tag right before. But why?? `git log TAG2..HEAD` give me the commits between TAG2 and HEAD. So since the first one contains way more commits `describe` uses the one with less commits. But I have no idea why `git log TAG1...HEAD` returns all merge commits which where tagged right before merging... does not make sense to me – zlZimon Apr 21 '21 at 11:49
  • What do you mean with "environment"? Are `dev`, `stage` and `prod` server names, repositories or something else? – Mikko Rantalainen Apr 21 '21 at 14:50
  • 1
    In a sense, `git describe` *never* shows the *latest* tag. It shows instead the *best* tag, as defined by the heuristics. But sometimes the "best" is the latest. If you reformulate your question a bit, it will probably be more answerable; you should probably address @MikkoRantalainen's comment here as well (I suspect these are all branch names but it's certainly not completely clear). – torek Apr 21 '21 at 16:04
  • thanks for the feedback I changed the question and removed everything wich is not needed. I hope it is more clear now – zlZimon Apr 22 '21 at 11:03
  • Are you sure that step 7 `git merge dev` is completed without errors? Try running `git checkout dev && git log --graph --oneline --decorate -n 5` to see listing where your branches are. – Mikko Rantalainen Jun 19 '21 at 16:16
  • Also, are you running *all the commands* on the same machine or some on the some another computer? There's a difference between local `stage` vs `origin/stage` (or whatever you remote is called, `origin` is just the default similar to `master`). – Mikko Rantalainen Jun 19 '21 at 21:15
  • all steps completed without errors and were run from the same machine. I added a screenshot, please note that the tags are different. so in the example above `v0.1` is `v0.17.0` and `v0.2` is `v0.19.0` – zlZimon Jun 22 '21 at 10:26

1 Answers1

4

You should write all the commands you actually run instead of trying to use English because it doesn't seem to explain the situation accurately enough. For example, your wording uses "merge into" and "merge to" which may or may not describe the same thing for you. For a merge, you usually do something like git checkout some-local-branch && git fetch && git merge origin/some-other-branch. All the details may be important if you don't understand the whole situation yourself for sure. And if you run some commands on e.g. remote machine over ssh connection, make sure to point this out, too.

From the question (as worded 2021-04-27T14:24:13+00:00) it appears that your Process 2 is missing git push --tags (or maybe git fetch) and if you try to run git describe somewhere else but the original repository (that is, your working directory in practise) you'll not see the new tag at all.

I'd suggest starting with git show NEWTAG in all workspaces (or "branches") you're trying to use. You should get the same SHA-1 on every workspace. You could also run git show HEAD to verify that the current HEAD actually matches what you think it should match. Also, if you can run gitk you can try running gitk NEWTAG HEAD to get visual repsentation of the problem or even gitk --all -n 10000 to show all branches up to 10000 latest commits.

If you cannot use gitk, you can also try running e.g. git log --oneline --graph --decorate -n 50. As an alternative, you can also run git log --oneline --graph --decorate -n 50 --format=%h%d to list the latest 50 commits from the DAG without titles so that you can share the results here in SO if you need more assistance.

Update after seeing the screenshot

Your branch master is not at the same position as any of your tags so git describe should not emit any given tag name as the sole output. Instead, it should say something like v0.2-4-gf5d6ced which basically means "v0.2 plus 4 patches with the HEAD pointing to SHA-1 starting with f5d6ced". The four patches for this example are a5312dc, 7dceb15, b4cd4f6 and f5d6ced which are not included in v0.2 below.

Here's an example I created:

*   f5d6ced (HEAD -> master) Merge branch 'staging'
|\  
| *   b4cd4f6 (staging) Merge branch 'dev' into staging
| |\  
| | * 1fa7a37 (tag: v0.2, dev) Updated testfile yet again in branch dev
* | |   7dceb15 (tag: test) Merge branch 'staging'
|\ \ \  
| |/ /  
| * |   a5312dc Merge branch 'dev' into staging
| |\ \  
|/ / /  
| | _   
| * 96cd0ac (tag: v0.1) Updated testfile in branch dev
|/  
* d626941 Added testfile in branch dev

Screenshot of the above textual repsentation

The v0.1 and v0.2 are annotated tags and the test is a non-annotated tag.

$ git checkout dev && git describe
Switched to branch 'dev'
v0.2

$ git checkout staging && git describe
Switched to branch 'staging'
v0.2-2-gb4cd4f6

$ git checkout master && git describe
Switched to branch 'master'
v0.2-4-gf5d6ced

$ git checkout master && git describe --tags
Already on 'master'
test-3-gf5d6ced

This is caused by the fact that when you create a merge, you create a new commit which obviously will have its own SHA-1 identifier and the existing tag does not point to the merge because tags always refer to specific versions.

Are you sure you're not actually running e.g. git describe --abbrev=0 which selects just one tag from the most recent tags and may prefer the first parent for any given merge?

If you're actually trying to figure which tags your given branch already includes, you can run something like this:

$ git checkout master && git tag --merged
Switched to branch 'master'
test
v0.1
v0.2

or sorted by the time tags were created, latest first:

$ git checkout master && git tag --sort=-authordate --merged
Already on 'master'
test
v0.2
v0.1

And if you want just the latest tag, you can run

git tag --list --sort=-authordate --merged | head -n1

See git help tag for more details. For this case, the latest means authoring timestamp of given tag. For tags the author timestamp and commit timestamp are equal but this is not forced anywhere as far as I know. If the difference matters to you, only you decide which timestamp you need.

Further explanation for your specific "error" case: you didn't actually run git describe as you claimed but git describe --abbrev=0 which lists the closest tag. Note that this is in DAG topology and it may be totally different from latest or newest tag. For your example case, both v0.17 and v0.19 have distance 1 from the HEAD of branch staging and 2 from the HEAD of master. In addition, the older tag comes from the first parent which is why you get v0.17 as the response. I'd recommend using git tag --list --sort=-authordate --merged | head -n1 instead if you want the latest tag that's included in given branch. However, I'd strongly recommend tagging master branch releases instead of random patches in development or staging branches. Then you could use just git describe without any flags

Mikko Rantalainen
  • 14,132
  • 10
  • 74
  • 112
  • 1
    sorry for the late reply, but I followed your suggestion to use more commands then english – zlZimon Jun 18 '21 at 12:16
  • I also added a screenshot of the graph, I hope that helps – zlZimon Jun 26 '21 at 11:22
  • I still cannot understand how you can get the described output from `git describe` without any extra flags. See the example I added to the end of this answer. – Mikko Rantalainen Jun 27 '21 at 10:18
  • I am sorry, I omitted the last bit. I now updated the question to make it cristal clear. Also please note that all my tags are annotated – zlZimon Jun 28 '21 at 12:38
  • 1
    `git describe --abbrev=0` will show the "closest" tag. For your example case, both `v0.17` and `v0.19` have distance 1 from the HEAD of branch `staging` and 2 from the HEAD of `master`. In addition, the older tag comes from the first parent which is why you get `v0.17` as the response. I'd recommend using `git tag --sort=-authordate --merged | head -n1` instead if you want the *latest* tag that's included in given branch. However, I'd strongly recommend tagging master branch releases instead of random patches in development or staging branches. Then you can use `git describe` without any flags – Mikko Rantalainen Jun 29 '21 at 11:02
  • 1
    And if you're going to script this, I'd recommend `git tag --list --sort=-authordate --merged | head -n1` so that you don't depend on heuristics but explicitly request list of tags from git. – Mikko Rantalainen Jun 29 '21 at 11:07
  • I hope you now understand why it's always a good idea to write the full commands you're using directly into the question. If you leave even a single flag away, the correct answer may change. – Mikko Rantalainen Jun 29 '21 at 11:08