First of all, you can read about the difference between tags and branches here:
How is a tag different from a branch? Which should I use, here?
Suppose you do the following:
git checkout master //go to branch master, say at commit x
git checkout -b newbranch //create a new branch called newbranch that also points to x
git commit -a -m some_branch_commit_1 //add a commit to newbranch
git tag tagged_my_commit //tag your commit
git checkout master //go back to master
git commit -a -m "Something" //add a commit, say y to master
git checkout newbranch //go back to newbranch
git rebase master //create a copy of the commits on newbranch so that they now split of from y instead of x
In this case, a new copy of commit some_branch_commit_1
will be created. However, the old one still exists (it was tagged tagged_my_commit
) so it will never disappear.
Basically, you now have two copies of the same commit, one of them is not on a branch with a particular name.
Suppose however you didn't tag that commit, then in principle it could be removed by git. However, deleting such commits (garbage collection) only happens from time to time. This can explain why commits that shouldn't keep on existing still are in your repostiroy. If you want to read more, see https://git-scm.com/docs/git-gc
As noted in the comments, this does not only happen with rebases. Any form of rewriting (e.g., amending commits, changing the pointer of a branch, ...) can lead you to this situation.
EDIT as requested: another example
git checkout master //go to master, say at commit x
git commit -a -m "I did something" //create a commit, say y1
git tag tagit //tag your commit
your history now looks like this
y1 = master = tagit
|
x
Now do the following
//edit some file
git commit -a -m "I did something (more)" --amend //change commit y1 such that it now also takes changes to the other file into account, say this is y2
In that case your history looks like this
y1=tagit y2=master
| /
| /
| /
| /
| /
| /
| /
| /
x
which seems to be like in your situation