We are using Bamboo and Plan Branching to manage our feature-branch and release cycle.
Synopsis (in case your curious) Essentially, whenever a commit is pushed on a feature branch, Bamboo kicks in and merges the development trunk to the branch to confirm the developer has broken anyone else's accepted (approved via pull request) commits that are in the development trunk.
However, even if a developer closes the branch, or the pull-request approver closes the branch, bamboo kicks in an creates a final merge commit thus re-opening the branch. This has created a lot of clutter in the source-control as people forget to manually go back and close their branches again (as they've already closed them).
I wanted to pipe together some commands to script the closing of any branch that hasn't been committed too say in the last 5 days? Or perhaps prior to a revision number?
hg log, hg status, or hg log --template "{date|localdate|rfc822date}\n"
Seem promising, but I'm sure someone has to have concatenated a few calls?
Or if there is a way to add some instruction to Mercurial that would be great as well!
Related
I'm fairly new to version control in teams. So far I've mostly used it solo.
I've read that the following workflow is recommended:
Commit locally, pull master, merge master into my branch, merge my
branch into master, push. Several times a week or even day
So that's what I tried to do. However, when I was done with my feature, and tried to push, tortoise hg told me, that this would create new remote heads.
hg help push tells me about two options:
Merge first: Did that
Use -f: I know enough not to do that.
I think I understand the concept of rebasing - which I don't think applies here, since I'm the only one who did anything in this commit tree. Of course I've pulled.
So my question is: How can I resolve this specific situation?
Also, recommendations for where to learn proper version control workflow would be nice. Everything I find tells me what the commands are, but I've failed to find clear instructions on when to use them.
I've added a picture of the project. Commit 147 was mine, and I could push it just fine. All oher commits are also made by me.
hg reports a "head" for every named branch. In your screenshot, you are needing to push rev 154, which is the head of your kjeld branch. It is an outgoing changeset because you are pushing rev 155 and you must therefore push 155's entire history as well. Others will get that branch when they pull your changes and will have a head on their version of kjeld (note that it will most likely not be numbered 154 since those numbers are repo specific). You will be fine though since that head is a close-branch changeset so it will not appear in their default list for hg heads and hg branches.
One way to avoid your current issue is to use bookmarks to temporarily note what that head represents e.g. issue-45, big-feature-2, etc. and only push when merged into mainline development.
For us, we set up a "private" repo for each dev on the server where they store/backup work in progress. It is expected that there are multiple heads, dead branches, and other gunk in these "private" repos. The dev repo, however, only ever has a single head and must pass the build and build tests.
In response to your comment about your "private" branch: When you push your tip you will also push your branch named kjeld. Others who want to work on that code must pull it to get the tip of your development. It will not be a "private" branch.
we are a team of 3 developers using Mercurial as a SCM tool, and I recently noticed the current heads (revision numbers) are different between the 3 of us, after everybody has pulled the latest changeset from the central repository. I'm at 2483 and the others are at 2482 (numbers are arbitrary, but mine is +1 compared to the others'). Is this something normal? Because it looks to me as a problem.
We've recently worked on a branch, then switched back to the default branch and merged with the branch. The only thing I can think of is that 2 of us did the merge and pushed the merge to the central repository, instead of only one doing the merge, pushing, and the others pulling the merge. Can someone help with an idea, maybe this is normal after all?
Things to look at:
12455:8b908304cb1c is the revision number of my current head. 12455 is a local number, it's only valid for my local repository, it's not global identifier portable between my own repos, or between my repos and my coworkers. 8b908304cb1c on the other hand is a globally usable identifier. 8b908304cb1c locally can be used to refer to the exactly same revision in every repository that contains that commit
hg outgoing will show you what needs to be pushed. hg incoming will show you what you've forgotten to pull.
hg heads --topo will show you the topological, unclosed, heads. This will quickly show you if you've got unmerged changes in a branch, or multiple heads in a single branch.
I have a small team and I would like to do the following:
I have my trunk, I'll just call it TRUNK
Now, TRUNK is a project that's already in production and running. Now, the inevitable defects come in, but into bugzilla and are assigned to users.
Each user clones TRUNK to their local repositories and makes changes and pushes them to a directory TRUNK/projects (projects is not a clone of TRUNK, just a regular directory)
Now, the day comes where I want to create a new build called RELEASE and I want to merge some of the bug fixes (not all, just some) into RELEASE.
Notice, I am not committed to the idea of having TRUNK/projects/[bugfixes list], but that's what I currently have now and am more than open to any / all suggestions.
What are some ideas? Is there something I can do / should do differently? Again, I am open to any / all suggestions, including completely changing the above procedure (except for using Mercurial as that's what the company makes us use)
There are two ways to do this and they diverge not at release time, but when you do the bug fixes depending on what parent you give the bugfix changesets. The "good" way uses only push, pull, and merge. The less good way (it's not entirely bad, but it's certainly sub-optimal) is called cherry picking and it has drawbacks. The tricky part is that whether or not you're going to be able to move bugfixes into RELEASE via merge without moving everything from TRUNK into RELEASE is something you have to decide before you make that change.
Here's a really complete answer for a similar question that explains what's going on: Some help with merging legacy branch in Mercurial
The key concept though, is that you can merge a changeset into any branch you want but it brings with it all of its ancestor changesets. So you want your bug fixed to have minimal ancestry. That means fixing a bug not in a new changeset in TRUNK that happens to be the latest feature you added, but instead, first, hg updateing to a changeset that already exists in both your TRUNK and your RELEASE, and there are two great candidates for that. Either:
the changeset where RELEASE and TRUNK diverged
or
the changeset where the bug was introduced
My preference is for the later. If a bug was introduced in changeset 666 then every clone, branch, and build that has changeset 666 will want your fix. So when fixing it just do:
hg update 666
.. fix the bug ..
hg commit -m "fixed bug 55" # creats changeset 999 which a new head
Then you can do this:
hg update TRUNK
hg merge 999
and you'll know you're only pulling in a single changeset. Later when you're ready to release you can do:
hg update RELEASE
hg merge 999
and you're again only getting the single changeset you want.
The advantage of this mode of working over cherrypicking (using export/import or transplant) is that your fix exists only once in your repo. If you have 99 different vendor branches for various finicky customers and you want to see if they have the fix for bug 55 you can just do:
hg log -r 'descendants(999) and heads(FUSSYCUSTOMERBRANCHNAME)'
and if there are no results then that customer doesn't have 999 and thus doesn't have the fix for bug 55 in changeset 666. When you re-do the same work with multiple changesets (which is the result of export/import and transplant) that's harder to verify.
Common practice is to create topic branches.
Each new issue/ticket/enhancement is commited into separate branch.
Anytime maintainer wants to make new release he can merge all (or only some) that branches into "default" or even new branch called e.g. "release_1_x".
To be more precise. Developer working on code can still clone repository, then create local branch and finally, after one or more commits to that branch, pushes local changes to one centralized clone (from which every other developer in team can pull/clone again).
How can I undo my last accidentally commited (not pushed) change in Mercurial?
If possible, a way to do so with TortoiseHg would be prefered.
Update
In my concrete case I commited a changeset (not pushed). Then I pulled and updated from the server. With these new updates I decided, that my last commit is obsolete and I don't want to sync it. So it seems, that hg rollback is not exactly what I'm searching for, because it would rollback the pull instead of my commit.
One way would be hg rollback (deprecated as of Hg2.7, August 2013)
Please use hg commit --amend instead of rollback to correct mistakes in the last commit.
Roll back the last transaction in a repository.
When committing or merging, Mercurial adds the changeset entry last.
Mercurial keeps a transaction log of the name of each file touched and its length prior to the transaction. On abort, it truncates each file to its prior length. This simplicity is one benefit of making revlogs append-only. The transaction journal also allows an undo operation.
See TortoiseHg Recovery section:
This thread also details the difference between hg rollback and hg strip:
(written by Martin Geisler who also contributes on SO)
'hg rollback' will remove the last transaction. Transactions are a concept often found in databases. In Mercurial we start a transaction when certain operations are run, such as commit, push, pull...
When the operation finishes succesfully, the transaction is marked as complete. If an error occurs, the transaction is "rolled back" and the repository is left in the same state as before.
You can manually trigger a rollback with 'hg rollback'. This will undo the last transactional command. If a pull command brought 10 new changesets into the repository on different branches, then 'hg rollback' will remove them all.
Please note: there is no backup when you rollback a transaction!
'hg strip' will remove a changeset and all its descendants. The
changesets are saved as a bundle, which you can apply again if you
need them back.
ForeverWintr suggests in the comments (in 2016, 5 years later)
You can 'un-commit' files by first hg forgetting them, e.g.: hg forget filea; hg commit --amend, but that seems unintuitive.
hg strip --keep is probably a better solution for modern hg.
hg strip will completely remove a revision (and any descendants) from the repository.
To use strip you'll need to install MqExtension by adding the following lines to your .hgrc (or mercurial.ini):
[extensions]
mq =
In TortoiseHg the strip command is available in the workbench. Right click on a revision and choose 'Modify history' -> 'Strip'.
Since strip changes the the repository's history you should only use it on revisions which haven't been shared with anyone yet. If you are using mercurial 2.1+ you can uses phases to track this information. If a commit is still in the draft phase it hasn't been shared with other repositories so you can safely strip it. (Thanks to Zasurus for pointing this out).
Since you can't rollback you should merge that commit into the new head you got when you pulled. If you don't want any of the work you did in it you can easily do that using this tip.
So if you've pulled and updated to their head you can do this:
hg --config ui.merge=internal:local merge
keeps all the changes in the currently checked out revision, and none of the changes in the not-checked-out revision (the one you wrote that you no longer want).
This is a great way to do it because it keeps your history accurate and complete. If 2 years from now someone finds a bug in what you pulled down you can look in your (unused but saved) implementation of the same thing and go, "oh, I did it right". :)
hg rollback is what you want.
In TortoiseHg, the hg rollback is accomplished in the commit dialog. Open the commit dialog and select "Undo".
In the current version of TortoiseHg Workbench 4.4.1 (07.2018) you can use Repository - Rollback/undo...:
Its workaround.
If you not push to server, you will clone into new folder else washout(delete all files) from your repository folder and clone new.
I believe the more modern and simpler way to do this now is hg uncommit. Note this leaves behind an empty commit which can be useful if you want to reuse the commit message later. If you don't, use hg uncommit --no-keep to not leave the empty commit.
hg uncommit [OPTION]... [FILE]...
uncommit part or all of a local changeset
This command undoes the effect of a local commit, returning the affected
files to their uncommitted state. This means that files modified or
deleted in the changeset will be left unchanged, and so will remain
modified in the working directory.
If no files are specified, the commit will be left empty, unless --no-keep
Sorry, I am not sure what the equivalent is TortoiseHg.
after you have pulled and updated your workspace do a thg and right click on the change set you want to get rid of and then click modify history -> strip, it will remove the change set and you will point to default tip.
I ran into this issue recently, although my situation was slightly different - I had already pushed the commit I wanted to undo. I solved my problem with hg backout <revision-code>. It seems to work in a similar way to git revert. From this answer:
backout: create a new commit that is the inverse of a given commit.
Net effect is an undo, but the change remains in your history.
In TortiseHg this can be done by right clicking the commit you wish to undo and selecting Backout.... TortiseHg doc here.
I think there's an argument for creating a new undo commit instead of removing the previous commit outright. From this article about git revert:
Instead of removing the commit from the project history, it figures
out how to invert the changes introduced by the commit and appends a
new commit with the resulting inverse content. This prevents Git from
losing history, which is important for the integrity of your revision
history and for reliable collaboration.
So I have a mercurial repository that is the "blessed" repository that I will have open release cycle branches, for example Release1, Release2 etc.
When a dev is working on a release cycle they will pull down Release1, then on their local machine branch for Bug1, Bug2 and fix those.
What command sequence needs to happen for the devs to correctly close their Bug branches, merge the changes into the Release1 branch so that when the changes are pushed to the server no branch information about Bug1, Bug2 etc will be pushed to the server?
If you're using named branches the branch information about bug1 will always be pushed to the server. Named branch names are parts of their changesets and never go away or get changed. You can cause them to not show up in default branch lists by using the --close-branch option to commit, but they're still there and listable.
If you want a branching model where the branch names don't escape Mercurial provides some other branch options that may suit your needs better:
http://stevelosh.com/blog/2009/08/a-guide-to-branching-in-mercurial/
If someone suggests using the 'TransplantExtension' to merge the branches in and hide the branch information, don't listen -- it's a terrible idea.