While the UI of Bitbucket allows to tag a given commit of a mercurial repository, I can't find a way (web-based or command-line) to remove the tag, which could be added by mistake (actually, there is no confirmation prompt to add it). When used to control releases, this kind of mistake might be a major problem.
Mercurial has a built-in help mechanism for all commands. In this case, hg help tag
shows:
options:
-f --force force tag
Let's add a tag and then move it:
$ hg init foo
$ cd foo/
$ touch a
$ hg add a
$ hg commit -m 'add a'
$ hg tag 0.1.0
What is the history?
$ hg log -G
# changeset: 1:9352d8865ee5
| tag: tip
| summary: Added tag 0.1.0 for changeset a4cab63b7c86
|
o changeset: 0:a4cab63b7c86
tag: 0.1.0
summary: add a
Ahh, we changed our mind. We are missing one file. Let's add it (and so
add something to the hg history):
$ touch b
$ hg add b
$ hg commit -m 'add b'
We would like to move the 0.1.0 tag to the tip. Let's try:
$ hg tag 0.1.0
abort: tag '0.1.0' already exists (use -f to force)
Quite clear. Let's try again:
hg tag --force 0.1.0
What is the history ?
hg log -G
# changeset: 3:04b62f2a9b16
| tag: tip
| summary: Added tag 0.1.0 for changeset 3d8bb8a977e6
|
o changeset: 2:3d8bb8a977e6
| tag: 0.1.0
| summary: add b
|
o changeset: 1:9352d8865ee5
| summary: Added tag 0.1.0 for changeset a4cab63b7c86
|
o changeset: 0:a4cab63b7c86
summary: add a
As we can see, the tag has moved to the new location.
For curiosity, how are tags stored? In a simple text file:
$ cat .hgtags
a4cab63b7c868638e51a45d93443b1a0eb56e1e4 0.1.0
a4cab63b7c868638e51a45d93443b1a0eb56e1e4 0.1.0
3d8bb8a977e6be693a30c30d7d7675d04623690f 0.1.0
If the .hgtags file has multiple entries with the same tag, the last one
wins. This is seen often when merging branches.
Left to the reader: clearly these changes are local. You have to push to
bitbucket to make them public.
EDIT
To answer the additional question: is there a way to remove a tag, or to rename a tag for the same commit ?
The safest way is not to rename the tag, it is to add the new tag name for the same commit (with hg tag -r REV). Said in another way: a single commit can have associated as many tags as you want.
It is also possible to remove the tag, simply by removing the corresponding line from .hgtags. This is delicate to get right, because there is one copy of that file per branch, and it could come back as the result of a merge.
Actually, it is possible to delete a tag. This can be done from the commit's view: the tag has a gray X next to it.
The tagged commit can be found on the commits' page. It is the top-most one for the tag.
Notes:
This answers the question "How to untag in Bitbucket" - I am using git, not mercurial.
I have still added the answer, because this page ranks high in search engine results.
Related
I've created a changeset which contains a number of individual changes. I've realized that one of those changes might not have been a good idea, and I'd like to update my working directory to include only part of that changeset to work on, without throwing out the changeset itself.
In git terms, I want to do something similar to git checkout -p HEAD~, or the similar
git checkout -b newbranch
git reset HEAD~
git add -p
git checkout -- .
How can I do this in Mercurial?
Read carefully hg help revert, pay special attention to -r option and NAME (ordinary list of fileset).
In your case (single changeset, part of which you want to eliminate from Working Dir), you have to:
hg up to the this changeset
hg revert -r "p1(.)" set:SOME-FILESET or, instead of fileset ("set:PATTERN" part), just "... FILE FILE2 FILE3 FILEN"
As result, you'll get in one readable command modified Working Directory with only needed part of changes in it
On GitHub, you can compare changes between two branches or tags by appending /compare to the repository path.
For example: let's say I wanted to view all commits for Notepad++ since the last major release. (Comparing v7.4.2 against HEAD)
I take the project's repository URL, (https://github.com/notepad-plus-plus/notepad-plus-plus/), and append compare/v7.4.2...HEAD.
While I can use HEAD to refer to the last commit in a project's history, I can't figure any way to reference the first commit in a project's history.
Is it possible to compare a tag or commit against the first commit in a GitHub project's history?
I've already tried compare/TAIL...v7.4.2, but that just leads to a page stating "There isn’t anything to compare"
There's no symbolic ref like HEAD that references the first commit. One way to find the initial commit ID is to clone the repository and run git log --reverse or git rev-list --format=%B --max-parents=0 HEAD, which will list all commits accessible from HEAD with no parents. The initial commit will be included in that list. You can then use its ID to compare it to another commit or a tag on GitHub.
Here's an example with the notepad-plus-plus repository:
$ git log --oneline --reverse | head -n 1
ec7b0c2d v4.2 ready
Comparing the initial commit with v7.4.2 on GitHub.
I am working on a large project, with a main repository and multiple subrepos, organized like this:
main-repo
sub-a
sub-b
sub-c
Each person working has one or more named branches of their own. I am working in a branch that we will call shastings-dev and a co-worker has a branch that we will call coworker-dev. (Both of these branches exist in main-repo, sub-a, and sub-b; neither exists in sub-c and we are both using someone else's branch for that one.)
My problem is that I can no longer merge changes from coworker-dev without creating a new head somehow. This sequence of commands has the unexpected effect:
hg pull
hg branch # prints: shastings-dev
hg merge --tool internal:other coworker-dev
hg commit -m "merge coworker-dev" --subrepos
hg push
The hg push prints this message:
abort: push creates new remote head 945a60694252 on branch 'shastings-dev'! (in subrepo sub-a)
EDIT -- I am breaking the question here and putting the answer. The rest of the question will be left intact below for anyone who is really interested in all the details.
The solution: for each subrepo that needed a merge, change directory to the subrepo and follow these steps:
hg update --clean shastings-dev
hg merge --tool internal:other coworker-dev
hg commit -m "merge coworker-dev"
hg push
(I did this for subrepos sub-a and sub-b. For sub-c I just ran hg update correct_branch_name to make sure that it was at the head as well.)
Then, once each subrepo has been properly updated, return to the containing repo, and:
hg commit -m "commit .hgsubstate after merging in subrepos"
hg push
As a result of this experience, I am going to adopt a new rule:
If you have problems with subrepos, always retry the commands in the individual subrepos.
What confused me was that hg update --clean switched all the subrepos, but didn't actually update them. The heads for the subrepos belonged to a different branch than the one showing with hg branch. As a result, #zerkms's comment was correct: the subrepos actually were not on the head and the merge really was creating a new head.
In other words, even if hg id shows that the main repo is at the head, that doesn't mean the subrepos updated properly and are also at their respective heads. Check the subrepos individually to figure out the real state of things.
EDIT -- rest of original question is below.
My first thought was that my local copy of the repo was somehow scrambled. So I cloned an absolutely fresh copy of the repo, verified that hg pull didn't bring anything new in and tried the merge/commit/push again. Same problem.
I have tried doing the merge/commit/push in the subrepo then doing commit in the main repo (to update .hgsubstate) and then doing merge/commit/push in the main repo. No joy.
I have tried using TortoiseHg on Windows to clone the repo, update to branch shastings-dev, and then merge/commit/push. Same problem.
So now my questions:
Why is a new head being created? Am I doing something wrong, is there something wrong with my branch, or is this expected behavior?
What should I do? Can I eliminate this multiple heads problem, or should I push with -f and then close the older of the two heads with hg commit --close-branch?
What bad things might happen if I use hg push -f? My personal rule is "don't do that unless you are a Mercurial expert" and I'm not a Mercurial expert. (So my actual personal rule is "never use hg push -f.")
By the way, I am not working on any files that coworker is working on. At this time I have only minor differences from coworker-dev and I would be willing to totally lose all history on branch shastings-dev, as long as I can get a working up-to-date branch with the same name. (If I lose my changes I am willing to copy the changed files over again. I just want Mercurial to work as expected again.)
EDIT: I am on a branch head when I do the above.
$ hg heads
changeset: 1515:803ea844dc8a
branch: coworker2-dev
tag: tip
user: coworker2
date: Tue Oct 08 17:33:31 2013 -0700
files: .hgsubstate
description:
Fixed some stuff in the foo bar.
changeset: 1513:1e76e6a43d83
branch: coworker-dev
parent: 1509:5e5392aded0a
user: coworker#place_where_i_work.com
date: Tue Oct 08 16:44:04 2013 -0700
files: foo.java bar.java baz.java quux.java
description:
Added more support to the foo bar for release.
changeset: 1422:8705d62db8f2
branch: shastings-dev
user: shastings#place_where_i_work.com
date: Wed Oct 02 21:08:39 2013 -0700
files: .hgsubstate
description:
Finish adding files
...many others not copied here...
$ hg id
8705d62db8f2 (shastings-dev)
$ hg update --clean shastings-dev
resolving manifests
0 files updated, 0 files merged, 0 files removed, 0 files unresolved
$ hg id
8705d62db8f2 (shastings-dev)
$ hg merge --tool internal:other coworker-dev
...much output not copied here...
$ hg commit -m "merge coworker-dev" --subrepos
...much output not copied here...
$ hg push
pushing to https://path/to/repo/dir/main-repo
pushing subrepo sub-a to https://path/to/repo/dir/sub-a
searching for changes
new remote heads on branch 'shastings-dev'
new remote head 85d8faada6c4
new remote head 90ce145db695
abort: push creates new remote head 85d8faada6c4 on branch 'shastings-dev'! (in subrepo sub-a)
(you should pull and merge or use push -f to force)
As I said, when I had problems, I re-cloned everything. So the status is clean: I have no modified files.
Also, I have one other branch, and I tried the above sequence with the other branch. It happened again just as described. So, if anything is wrong, I figure it must be wrong in branch coworker-dev and not in my own branches.
Why is a new head being created? Am I doing something wrong, is there something wrong with my branch, or is this expected behavior?
You're not on the branch head, so merge creates another one
-- A (you're here) --- B --- C (head #1)
\
D (merge, head #2)
So you need to make sure you're on the head using hg id and hg heads. And if no - hg up
What should I do? Can I eliminate this multiple heads problem, or should I push with -f and then close the older of the two heads with hg commit --close-branch?
You should solve the real issue. See the advice above
What bad things might happen if I use hg push -f? My personal rule is "don't do that unless you are a Mercurial expert" and I'm not a Mercurial expert. (So my actual personal rule is "never use hg push -f.")
My personal rule is - to never use -f. After 4 years of experience with mercurial I don't see any good reason to use it at all. What may happen - as soon as there are 2 heads, what would hg up branchname do? What would hg up do?
I am new to a repository and all I have is a CVS branch name. I am trying to determine the branch point or base point of this branch. How can I find the pre-branch tag? Is it possible?
To be more clear - the procedure to create a branch is as follows:
create base tag:
$ cvs tag BASE
Create branch:
$ cvs tag -r BASE -b BRANCH
Taking the above example I know BRANCH - I am trying to find BASE. I have searched for quite a while and the only thing that comes up is how to create the pre-branch tag and branch (shown above), but nothing comes up on how to find out what the pre-branch tag is based on the branch name.
Thanks,
- Chuck
With the commmand
$ cvs status -v {file}
You get the tags for the {file}.
The output will be something like (in the end of it):
Existing tags:
tag_name_1 (revision 1.1)
BASE (revision 1.2)
BRANCH (branch 1.2.1)
Then you'll know what is your branch revision, and the previous revision. In the example, you know your branch name (BRANCH). Its revision is 1.2.1. The previous is 1.2, and the tag for this revision is BASE.
Maybe the revision numbers in the example aren't in the way CVS do, but you can get the idea.
Basically, what I want to try is pulling hg revisions from a branch of an experimental repo into a clone of mainline. But I want to discard the branch name so I can push directly into the server-side mainline repo. It's probably best to give a simple example:
hg init hg_mainline
pushd hg_mainline
touch foo
hg add foo
hg commit -m 'foo'
popd
hg clone hg_mainline hg_experimental
pushd hg_experimental
hg branch bar_branch
touch bar
hg add bar
hg commit -m 'bar'
popd
pushd hg_mainline
hg pull ../hg_experimental
hg log
As you can see, the mainline now includes a rev with "branch: bar_branch." I don't want this revision to have a branch (i.e. it should be default).
It is okay if this requires rewriting history with rebase, transplant, or another tool. I have tried both of these, but couldn't get it working. The most recent revision hash may end up different between the two repos.
So I want the topmost revision of hg_mainline to look like:
changeset: 1:xxxxxxxxxxxx
tag: tip
user: ...
date: ...
summary: ...
with no named branch.
Again, it's okay if the hash isn't preserved from hg_experimental.
I am currently using hg 1.6.2+55-18e1e7520b67 from an Ubuntu PPA.
EDIT:
I also used 1.3.1. I tested the below on both, and the results here are the same.
I got it working with transplant, but only with the grep -v kludge.
hg transplant -s ../hg_experimental 1 --filter "grep -v '^branch:'"
With:
hg transplant -s ../hg_experimental 1
hg export didn't work either, with or without an appropriate grep.
The changeset patch looks like:
# HG changeset patch
# User Matthew Flaschen <EMAIL>
# Date 1282942390 14400
# Branch bar_branch
# Node ID b8e36efea72642f0a0194301489d5c48f619a921
# Parent 85d9b9773d4ec09676dfcc4af89c142c46279444
bar
I exported from experimental with:
hg export 1 -o '/tmp/%b_%H_%R'
and tried to import to mainline with:
hg import /tmp/hg_experimental_b8e36efea72642f0a0194301489d5c48f619a921_1
It fails with:
abort: no diffs found
EDIT 2:
As noted, the export method failed only because the files were empty. It works correctly with --git or with non-empty files.
The simplest solution is use hg export from the experimental repo, and hg import into the main repo. By default, hg import won't apply any branch information in the patch. The downside is that they'll show up as different changesets in the two repos -- hg incoming in the experimental repo will show the changes you just exported/imported -- so after you do this, you may be better off deleting and recreating the experimental repo if you plan on doing any more experimentation.
EDIT: From the hg_mainline repository:
hg export -r 1 -R ../hg_experimental | hg import -
EDIT2: From hg help diffs:
Mercurial's default format for showing changes between two versions of a file
is compatible with the unified format of GNU diff, which can be used by GNU
patch and many other standard tools.
While this standard format is often enough, it does not encode the following information: (snip)
creation or deletion of empty files
The test files are empty in your test script, so you need to either enter something into them, or use the --git option to hg export.
The transplant extension already scraps the branch name:
cd hg_mainline
hg transplant -s ../hg_experimental 1
should do it for you. If you're finding that's not the case you can always use the --filter modify the changesets (perhaps just using grep -v) on the way in.
I will note that if you can come up with a work flow that avoids transplant and retains hashes you're better off. Avoiding named branches entirely makes this easier -- anonymous branches perhaps with bookmarks work as well or better.