Is it possible to react to a push to a repository with a hook and merge all new heads that are created by this push?
My use case for this is the following:
I'm trying to design a repository that would only allow very specific changes with a commit hook. The basic idea is that it is only allowed to replace existing files with better files (better is something that can be checked by an external program). Each user could clone a central repository and commit changes to the clone. When a user pushes his changes to the central repository, a hook checks whether the quality increases along each branch and rejects the push otherwise. If users push out of sync, this will create multiple heads that could in theory be merged automatically (taking the best version of each file).
Your hook can do whatever you want, in principle. Write a program that handles the evaluation and merging you describe, and associate it with the changegroup hook, which is triggered whenever someone pushes a group of changesets to the repo, or the incoming hook, which is executed separately for each arriving changeset.
Related
I have projectA execute projectB. ProjectB writes ProjectA's build info to ProjectA.buildInfo.
I have a Mercurial repo for projectB, and use HgFlow (git-flow workflow) using sourceTree.
I would like ProjectA.buildInfo to be part of the develop branch of my mercurial repo, but not part of the default branch.
When I have removed ProjectA.buildInfo from default, develop eventually merges back into default and brings the unwanted file with it.
You simply have to pay attention to the merges you do. hg remove the unwanted file every time you merge your development branch back into default.
In order to avoid this (easy) mistake to happen, I suggest to ward yourself against that by means of a commit hook. That hook should check whether the commit so done on default branch and fail when it detects the unwanted file(s) being added. Additionally run the same or similar as pretxnchangegroup hook on the central repository (if any).
Check hg help config and search for help on hooks therein. We use a hook to avoid people committing build artefacts to every branch, you could possibly extent that: https://hg.openttdcoop.org/misc/files/tip/mercurial/hooks/check_commit.py
I think it is common practice of many development teams to create new features or bugfixes in a separate feature clone repository and pull and merge back if the feature/bugfix is ready.
However, sometimes I don't want to include all of incoming changes. To harness all the power of DVCS to review incoming changes I think it is necessary to be able to fully modify and select single aspects of the incoming changes.
What's the preferred workflow for this scenario?
As far as I know transplant extension offers the possibility to pick single changesets but I would also like to prune/pick on a path/file base e.g. to exclude some test scripts or stuff like that, that isn't required for the final feature anymore.
Since transplant is an extension, what's the official way to have a "clone, change, ... review" cycle in HG?
Mercurial is changeset-centric VCS, thus - operational object is changeset, cherry-picking inside changeset not possible at all
In Mercurial you can't discard some of incoming changesets in bundle (but can do in Git, AFAICR)
It's not official way in any form, just personal POV: because pull produce anonymous branch, before merging this branch with mainline you can edit branch content in order to exclude unwanted parts, using
histedit - delete changests, join
MQ - remove changeset from branch, edit content of changeset (convert to MQ-patch, edit, finish, reorder)
I am writing a open source project, I did all the work at my machine and now I want to push the project do Codeplex.com, but I dont want to send all the old history.
Its possible to push all files in just one revision to Codeplex and continue with my history locally? Something like a Push And Collapse
No - a DVCS relies on the fact that you synchronise all history between members in the distribution set.
If you want to get rid of the history though, prior to pushing to Codeplex you can do the following:
Clone your local repository to a revision before the history you want "removed". We'll call the clone "Repository B".
Update repository A to the tip that you want to apply. Grab the changes, and copy the files to your cloned repository B. You can greate a bundle or patch, but for brevity here I'm just going with the quick and dirty :)
On repository B, commit a single changeset with all those changes.
From now on, repository B is your master. Push this to Codeplex.
As you can see, you can't have historical changeset data on one clone that partakes in a synchronisation with another, but before you've pushed to Codeplex, you can mush all those changes into a single commit - so long as you're happy to lose the history locally too.
An alternative is to use Mercurial Queues to "fold" history, but it needs to be done before you push to Codeplex - check out this wiki page for more information.
Check out the CollapseExtension.
Using a Macbook, I am worried that if the hard drive is on the road and it goes bad, then 3 days of code can all be lost.
So I actually have a tmp repository on our main server computer, and I can hg push to it. The dilemma is, I can't push unless I commit first, and from previous experience, we shouldn't commit unless we are ready to push to a central server (to share code with coworkers, merge, etc) (the reason is, we can't push selected files -- we have to push all committed files or push nothing). So how to solve this?
Is there a way to say, "copy all MODIFIED FILES (and added files) to /user/peter/2010-06-18 on the central server?)" or not commit but somehow get it onto the server?
The normal way is to just commit. With a DVCS one is urged to "commit early, commit often". Commit locally often, then for backup purposes push to your tmp repo on the server frequently. When you're happy with your work, then you push from your tmp repo to your shared "central" server.
There's no need to make sure everything compiles after each changeset, the norm is to just make sure that each back of changesets you push leaves the 'tip' in a compileable state. Generally one triggers the continuous integration build server to turn a builds after each group of changesets (changegroup) arrives, and it only considers the 'tip'.
If you really, really can't stand having changesets that can't stand on their own, then a mercurial pro would use mercurial queues to keep a versioned patch pushed to a separate queue repository while working on it. Someone willing to play with fire would use the collapse extension to merge the sequence of changesets into a single changeset before pushing to the shared repos.
Of the three options presented:
fix your workflow so that the central repo can handle changesets that don't compile, so long as they're part of a changegroup that compiles
use mercurial queues to keep a patch in a versioned patch repository
use the collapse extension to rewrite history (play with fire)
I think the first is most commonly done, and generally the "right" way.
We've just recently switched over from SVN to Mercurial, but now we are running into problems with our workflow. Example:
I have my local clone of the repository which I work on. I'm making some highly experimental changes to our code base, something that I don't want to commit before I'm sure it works the way it is supposed to, I don't want to commit it even locally. Now, simultaneously, my co-worker has made some significant improvements/bug fixes which I need. He pushes his commits to our main repository. The question is, how can I merge his changes to my workspace without the requirement that I have to commit all my changes, since I need his changes to test my own code?
A more day-to-day problem we have with the exact same workflow is where we have a couple of configuration files which are in the repository. Each developer makes a couple of small environment specific changes to the configuration files, but do not commit the changes. These couple of uncommitted files hinders us from making any merges to our workspace, just like with the example above. Ideally, the configuration files probably shouldn't be in the repository, unfortunately, that's just how it has to be for here unnamed reasons.
If you don't want to clone, you can do it the following way.
hg diff > mylocalchanges.txt
hg revert -a
# Do your merge here, once you are done, import back your local mods
hg import --no-commit mylocalchanges.txt
There are two operations, as you've discovered, that makes changes from one person available to someone else (or many, on either side.)
There's pulling, which takes changes from some other clone of the repository and puts them into your clone.
There's pushing, which takes changes from your repository and puts them into another clone.
In your case, your coworker has pushed his changes into what I assume is your central master of the repository.
After he has done this, you can pull the latest changes down into your repository, and merge them into your branch. This will incorporate any bugfixes or changes your coworker did into your experimental code.
This gives you the freedom of staying current on other coworkers development in your project, and not having to release your experimental code until it is ready (or even at all.)
So, as long as you stay away from the Push command, you're safe.
Of course, this also assumes nobody is pulling directly from your clone of the repository, if they do that, then of course they will get your experimental changes, but it doesn't sound like you've set it up this way (and it is highly unlikely as well.)
As for the configuration files, the typical way to do this is that you only commit a master file template into the repository, with a different name (ie. an extra extension .template or similar), and then place the name of the real configuration file into the ignore filter.
Each developer then has to make his or her own copy of the template, rename it, and change it in any way they want, without the risk of committing database connection strings, passwords, or local paths, to the repository.
If necessary, provide a script that will help the developer make the real configuration file if it is long and complex.
Regarding your experimental changes, you should commit them. Often.
Simply you commit them in a clone you don't push. You only pull to merge whatever updates you need from other repos.
As for config files, don't commit them.
Commit template files, and script able to generate complete config files from the template.
That way, developers will only modify "private" (i.e. not committed) config files with their own private values.
If you know your uncommitted changes will not collide with the merge commit that you are creating - then you can do the following...
1) Shelve the uncommitted changes
2) Do the pull and merge
3) Unshelve the uncommitted changes
Shelf effectively stores your uncommitted changes away as into diff (relative to your last commit) then rolls back those files in your local workspace. Then un-shelving then applies that diff, bringing back your uncommitted changes.
Tools such as TortoiseHg have shelf built in.