If I have commit A
tagged with tag e.g. tag-A
, and then the next commit B
tagged with tag-B
; if I squash these 2 commits what happens to the tags? Will both be assigned to the squashed commit?
The tags won't move because a rebase rewrites history. The original commits will have the tags since tags don't move. Here's a picture:
Before:
(HEAD) B - tag-B
|
A - tag-A
|
X
After:
B - tag-B
|
(HEAD) C A - tag-A
|/
X
Here C
is the squash of A
and B
. It starts a completely new history, in which A
and B
will not participate. The branch head will move over to C
and will proceed from there.
go
projects that frequently squash branch commits. Go modules uses tags to pull in specific package version (even if they are off the main branch). My fear is during removal of old branches any tags will be orphaned (as their commits disappear) and break subsequent builds. –
Knick go
project to confirm if my final assumption is correct. –
Knick Will both be assigned to the squashed commit?
No.
Each tag points to a specific commit, and it never moves away from that commit on its own. The commits that each tag was pointing to is still alive, just not in any of your branches.
Squashing two commits creates a separate new commit, only with the contents of the original commits. This new commit will not have any tag pointing to it.
You can manually move those two tags to point to your new commit:
git tag -f tag-A
git tag -f tag-B
I think Mad Physicist's answer is great, but my curiosity made me want to reproduce this myself to look at the history. Here's an example that you can recreate locally to poke around the history.
First we need to create a blank repository:
cd ~
mkdir test_repo
cd test_repo
git init
touch file.txt
git add .
git commit -m "Create initial file"
Then we need to create a branch with multiple commits that will be squashed:
git checkout -b new_feature
echo "A" > file.txt
git add .
git commit -m "Added A"
git tag tag-A
echo "B" > file.txt
git add .
git commit -m "Added B"
git tag tag-B
This leaves me with the following history:
$ git log
commit 203a767647c3ebfc85b983dd573419013388b5aa (HEAD -> new_feature, tag: tag-B)
Author: Joshua Correia
Date: Thu Jun 16 12:06:20 2022 -0700
Added B
commit f16a24ae7b43110c98ee9a818db2a9f2ad5c8f3a (tag: tag-A)
Author: Joshua Correia
Date: Thu Jun 16 12:06:09 2022 -0700
Added A
commit a601965cd293c91820af6d9bc9bd9aa8965854a1 (master)
Author: Joshua Correia
Date: Thu Jun 16 12:05:57 2022 -0700
Create initial file
Now we can squash the commits and analyze what happens:
git rebase -i a601965cd293c91820af6d9bc9bd9aa8965854a1
Change "pick" to "squash" on the second line containing the commit "Added B" then save the file.
When we look at the history again, we see that the tags no longer exist in this branch's history. This is because tags are associated with individual commits, and these commits have been replaced by our rebase. Notice how the hash of HEAD has now changed since a new commit has been created to replace the two previous commits:
$ git log
commit 414d3cf4a12a3df293047de5271080d030cce119 (HEAD -> new_feature)
Author: Joshua Correia
Date: Thu Jun 16 12:06:09 2022 -0700
Added A
Added B
commit a601965cd293c91820af6d9bc9bd9aa8965854a1 (master)
Author: Joshua Correia
Date: Thu Jun 16 12:05:57 2022 -0700
Create initial file
These commits, however, have not been completely removed. If you run git tag
you can see that tag-A
and tag-B
still exist. You can git checkout tag-B
and see the history that existed when that tag was originally created, but this will put you in a detached HEAD state.
© 2022 - 2024 — McMap. All rights reserved.