Question

I have a large series of commits, with various version tags, i.e.:

root->x->x->1->x->x->x->2->x->x->3->x->4->x->x->x->5->master

I want to insert a new commit near the start of this. The problem is, I then need to go through and re-tag everything, because my tree ends up looking like this:

root->x->x->y->x->x->x->x->x->x->x->x->x->x->x->x->x->x->master
         \->1->x->x->x->2->x->x->3->x->4->x->x->x->5

Is there a way I can tag a specific commit, rather than a specific hash? So that when I do a rebase, the tags apply to the same specific commits, in the new tree, rather than the original commits?

Note: I am not interested in moralizing - please don't post any answers saying things like "you're doing it wrong" or "that's not how versioning is supposed to work" unless you can also provide a constructive alternative. I need a way to mark commits that will persist after a rebase, even if the only possible solution is "Git doesn't do that, use X instead".

Was it helpful?

Solution

Here is an alternative solution which I've seen many repositories use.

  • Create a branch for every major version you want to maintain.
  • Push fixes/updates to every branches. Use merging/rebasing/cherry-picking between them when possible to avoid repetitive work.
  • Tag commits in those branches with minor/patch versions.

Example:

  • You have a master branch.
  • You release version 1.0.0 pointing to the current master.
  • You continue to push to master and release a 1.1.0 version.
  • You then make a major refactor/backwards incompatible changes and release 2.0.0 version.
  • You could (and should) then make a 1.x branch pointing to the previous 1.1.0 version.
  • You then push a bug fix (in master) which affects both 2.x and 1.x versions.
  • Tag the commit as 2.0.1. Cherry-pick it in 1.x branch and tag that as 1.1.1.

There are variations to this workflow. You could always have a branch for your major versions and the master branch could be your active development branch for your next major version.

I think this is solving your problem by going deeper and addressing the root cause of your workflow which is - pushing a change to several versions.


I should also mention that changing what tags point to after you've pushed the tags is always bad. Very bad.

OTHER TIPS

...please don't post any answers saying things like "you're doing it wrong" or "that's not how versioning is supposed to work" unless you can also provide a constructive alternative. I need a way to mark commits that will persist after a rebase...

You're doing it wrong; that's not how versioning is supposed to work. 😄 Now for my constructive alternative—I do have one, and it's not "Git doesn't do this."

Using "tags" is out. If you do use git tags, even if you hack together some scripts that will delete the old tags and create new ones every time you rebase, your new tags won't be pulled by any other users collaborating with you, making the tags worse than useless as they would be actively misleading. (See LESS=+/DISCUSSION man git-tag for more info about this.)

However, there is a clean and elegant way to accomplish what you intend, without the use of tags. Note that it will not allow you to "pseudo-tag" a commit after the fact without rebasing to modify that commit, but since you're rebasing often already, I believe it will be perfect for your workflow.

The key to my pseudo-tag method is an understanding of a seldom-used method of specifying a git revision. See LESS='+/:/<text>' man gitrevisions to read up on it.

Decide on a text string that is short and won't show up in a commit message accidentally, and use it as a prefix for your pseudo-tags. For example, my-pseudo-tag-.

Then, for any commit which you want to pseudo-tag, modify that commit message (using rebase) to include the string, e.g., my-pseudo-tag-v0.7.5.

Now any time you want to refer to that pseudo-tag, e.g. to check out that version, or to create a new branch pointing there, use the git revision specifier like so:

git checkout :/my-pseudo-tag-v0.7.5
git checkout -b new_branch :/my-pseudo-tag-v1.3.0

Voila! Since your pseudo-tags are actually part of the commit message rather than a separate object pointing to the commit, they are unaffected by a rebase and can still be found only in the commit message where you expect to find them!

In other words, the way to mark commits that will persist after a rebase, is to include specific text in the commit messages that will only be found in that commit's message.

(Of course, if you are working with other people, you will have to dream up some way to ensure that they don't use the "reserved word" in their own commit messages...but that's beyond the scope of your question and my solution.)


Note: Please don't rebase commits that are available to others; it will make for future headaches. (This is directed at any future readers, not the Original Poster of this question whose workflow evidently demands rebasing.)

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top