We have this mercurial remote repository (lets call it repo01):
A --- B --- C --- D (default)
\
--- E --- F (other)
We need to grant access to the E-F branch to our client, but not the A-D one. On the other hand we need to keep track of changes to the E-F branch. So I was thinking that if we could somehow copy the E-F branch to a different remote repository, we could achieve just that.
So the other remote repository (let's call it repo02) would look like this:
E --- F (other)
Then we would work with both repositories and the client would just work with repo02. The question is, can this actually be done and if yes how?
Your question is the combination of these two questions:
Mercurial clone from a branch
Can I clone just the latest changesets of a repository instead of the entire history?
If you were going to copy the entire history of the branch other then you would just need to provide the -b option to hg clone:
hg clone http://your/repo -b other
For your purposes, you must combine it with some way of creating a shallow clone, which Mercurial doesn't natively support. Look at the extensions suggested in the top two answers to the second question above (https://bitbucket.org/facebook/remotefilelog and https://www.mercurial-scm.org/wiki/ShallowClone).
Related
My request probably seems to be a bit strange, but let me try to explain what I want to do.
So, first of all, what I want to version in the SCM isn't really the source code of something. It's JSON-files which contains statements to configure a specific server software (the server software saves its configuration in a database) using the provided api (there's a separate deployment tool). The only way to configure this software is using the api. So, the JSON looks something like this:
[{
"command": "command1",
"options": {
"option1": "value1"
}
}, {
"command": "command2",
"options": {
"option2": "value2"
}
}]
and so on and so on. So, now the configuration of this software is developed in Scrum and the result of each sprint needs to be a set of configuration commands which changes the software accordingly. This means, that the release package has to contain only the commands which weren't there the last release, too. So, what I currently think about (doing in git) is the following:
When a new sprint starts, I createa new branch in the repository and clear out all configuration files (there're several ones). I develop the configuration changes in the above mentioned JSON syntax and anything is fine. At the end of the sprint, the things in the branch is the release package (which only contains the delta configuration options from the previous release and this release). Now I would need to manually merge the branch back to the master to get an overall set of configuration options (e.g. to deploy a new server or rebuilt a server when it crashed or whatever). This is a manual task, however, I don't know how it could be done in a better way.
So, what I really want to ask into the round is:
Does anyone know a better solution to manage the configuration files? The goal is to have a delta of configuration options from the previous release, which could be used to update the configuration of an existing server, and a release package which contains all configuration statements (master). I would really love to see a better solution, however, I don't know any.
Thanks in advance for any help! If you've questions regarding what I ask for, feel free to comment :)
EDIT 1:
Based on the answer of #Marina - MSFT I thought about this a bit more. In git, something like this would probably work:
Let's assume a master like this:
|
C Another commit with changes to config2.json
|
B Some other commit with changes to config1.json
|
A First commit
|
So, currently the master tree contains two files, config1.json and config2.json, both have a JSON content like mentioned above.
Now, the next sprint (as an example, called "Sprint 1") starts and someone will create a new branch (git checkout -b dev for example). This person will also need to delete all files using git rm * and commits these chanes as the first commit to the branch, resulting in this graph:
---A---B---C---
\
D
D is the commit, which deletes all files. Now, I commit changes, which has to be done in this sprint (the configuration files will always only contain these changes). At the end of the sprint, I probably have a graph like this one:
---A---B---C---
\
D---E---F---G---H
So, because I only want E, F, G and H in the master, I don't merge the branch but instead cherry-pick all changes except D to master. Because I always edit the same files (config1.json and config2.json), git will ask me to merge these files manually (which is totally fine, I don't expect, that any tool can support me in merging files in the way I need to do it). After merging the graph should look like:
---A---B---C---E'---F'---G'---H' <--- master branch
\
D---E---F---G---H <--- dev branch
Now, I could rename the dev branch to Sprint 1 (git branch -m sprint1) or something like that and would have the delta release there and a full release in master. This should work, right?
If you want to do version control for files, git is a very popular way. For your detail requirement in git as below (if there has misunderstanding for your requirement, please correct):
Treat master branch as main branch, every time, after finish a sprint you can merge it to master branch, master branch is the last previous version, and the branch you are working on is the current, so you can use git merge to deal the conflict files with delta configuration.
Show as the below graph, when you start a new sprint, create dev1 branch (git checkout -b dev1) and make and commit changes for config files. Then merge dev1 into master branch (git checkout master and git merge dev1), you can solve the conflict files to keep delta changes, use git add . and git commit to finish the merge. The next sprint is similar.
______C_____ dev1
/ \
A---B--new commit--D---E--new commit--G--H master
\ /
_____F_____ dev2
Note: when you create a new bench new master, the config files can’t cleaned automatically, you need to delete the files or use git rm * to delete all files.
New solution bases on your edit:
A---B---C master
\
D---E---F---G---H dev
If you use cherry-pick, you need do 4 steps to make changes for E,F,G,H to master. Of cause it can work correctly, but there are also two ways to make it easier:
Rebase commit E,F,G,H to master branch for one command:
git rebase --onto master <commit id for D> dev
Because commitH has already contained changes for E,F and G, so you can only need to rebase/cherry-pick commitH to master branch. This will keep the master branch only contains the final edition for each sprint.
I am trying to work out how to use the Branch-per-feature approach in mercurial but having created a branch to work in, and merged it back to default, am unable to push my changes back up to my master repository. What is best to do?
I created a branch "Gauge customisation", did some work in that branch and then merged it back into the default. Carried on with a few more changes in default and now I want to commit this back to my master repository. But when I try I get:
abort: push creates new remote branches: Gauge customisation!
hint: use 'hg push --new-branch' to create new remote branches
I didn't think the branching would show up in the master repo and that by merging it locally I could somehow work in the branch (or potentially branches) and then when I've tested everything, push it up to the master repo.
Should the Gauge customisation branch still show up? Really I thought I'd only see default at this stage? But is that me not understanding the tools properly? Should I be creating the remote branch?
Ideally I'd like to be able to open a branch per feature and have 3 or 4 such branches running at any one time (it's the way my company works) so I'd like to get a solid grasp of things now.
Technically you could just commit the new branch to the master repo using --new-branch. As displayed in your screenshot, there is not really a new branch with a head from a topological view, but from a namespace view, i.e. when hg aborts your push, it just wants your explicit acknowledgement to add a new branch (name) to the remote repo.
However, for tasks like your's -- temporary feature branches -- a more common workflow is to not use named branches but anonymous/bookmarked branches or separate clones. Named branches usually are used for long-living branches like stable, legacy, and so on. If you create an anonymous/bookmarked branch and merge it back when its feature is finished, hg won't complain when pushing.
An often recommended reading in that context is A Guide to Branching in Mercurial.
Merging two branches does not get rid of either of them. You will need to close your feature branch manually by switching to it and doing:
hg commit --close-branch -m 'Closing branch'
I tried to merge two heads in Mercurial. After merging, I didn't commit and did some more changes. Then I tried to commit and got the following message:
abort: cannot partially commit a merge (do not specify files or patterns)
I'm using TortoiseHG as visual shell, and Beyond Compare for comparing and merging. And I'm relatively new to all of them.
What should I do to finish commit successfully?
Mercurial/TortoiseHg is correct in telling you that you should not partially commit a merge. Partial means that you do not commit all files at once.
The underlying reason for this message is that is gives you the wrong results. When you merge two changesets in Mercurial, you are creating a new changeset with two parent changesets. This merge changeset shows others how you want everybody else to combine the two changesets.
Let us imagine that you start with changesets A and B and want to merge them. This creates a graph like this:
... --- [A]
\
[M]
/
... --- [B]
Pretend that we added the line A! to a.txt in the A changeset and that we added B! to b.txt in the B changeset. Just two independent changes that does not conflict. If Mercurial allowed you to do a partial commit, then you could do this:
hg merge
hg commit -m 'Added A!' a.txt # creates M
hg commit -m 'Added B!' b.txt # creates M'
and the result is this graph:
... --- [A]
\
[M] --- [M']
/
... --- [B]
If you look at b.txt along the path B, M, M', then you will see that the line with B! was introduced in B, removed in M and reintroduced in M'!
This is not what you want from a merge changeset: a partial merge throws away changes from one branch just to introduce them again in a followup commit. Mercurial trusts you when you create M: it really believes that M contains the correct mix of A and B. In particular, if the B! line is removed in M, then it will remain gone when you merge M with other changesets.
So Mercurial is trying to protect you from creating a bad history by not allowing partial merges.
I think you have aliases in hgrc file. Try to remove [alias] section and commit again.
What should I do to finish commit
successfully?
One of the benefits of Mercurial (or git or any other DVCS) is that you can perform a commit at any point in your development process and it will be both fast and private. It will be fast because you should be committing to a local copy of the repository residing on your hard drive, and it will be private because no-one will see your change set until you push them to the server (or other master repository).
Therefore, to partially answer your question, the appropriate thing to do would have been to commit the merge without your addition changes, and then apply and commit your next wave of changes. If you are using TortoiseHG to peform the merge it will actually prompt you to commit the merge before leaving the GUI because this is the intended HG workflow.
That being said, I made some changes on a named branch (ie: new head), merged it back into the default branch, exited the TortoiseHG GUI without committing, made some more changes, and then committed with no problem. I will ask some clarifying questions below your original inquiry.
I had this problem because I had deleted some files. I reverted the files to restore them, then was able to commit. I then deleted the files and did a second commit.
I had the same problem and I was NOT specifying any files and using command-line.
The problem was the [default] section in my .hgrc
[defaults]
commit = -X project/web.config
So it added specific files to every commit-operation by default.
Review your defaults section for potential problems.
I had the same problem and the command I gave was
hg commit -m Merge with 1234
I figured it out after sometime that the commit message "Merge with 1234" has to be given in quotes as the command takes "with" and "1234" as file name params.
please check it in your case.
Is it possible to clone part of a Mercurial repository? Let's say the repository is quite large, or contains multiple projects, or multiple branches. Can I clone only part of the repository?
E.g. in Subversion, you might have trunk and branches. If I only want to get trunk (or one of the branches) I can just request [project]/trunk. If I clone the hg repo I'll get trunk and all of the branches. This might be a lot of information I don't want. Can I avoid getting this?
Alternatively, if I want to have multiple projects in one hg repo, how should I do this? I.e. so that I might just get one of the projects and ignore the others.
Yes you can. I'm sure you've moved on, but for the sake of those who will wander here later, I followed the docs at ConvertExtension, and wrote a simple batch script:
#echo off
echo Converting %1
REM Create the file map
echo include %1 > ~myfilemap
echo rename %1 . >> ~myfilemap
REM Run the convert process
hg convert --filemap ~myfilemap .\ ..\%1
REM Delete the file map
del ~myfilemap
cd ..\%1
REM update the new repo--to create the files
hg update
Name it something like split.cmd, and put it in the directory for the repo you want to split. Say for example you have C:\repos\ReallyBigProject, and a subfolder is C:\repos\ReallyBigProject\small-project. At the command prompt, run:
cd\repos\ReallyBigProject
split.cmd small-project
This will create C:\repos\small-project with a slice of the relevant history of revisions from the larger project.
The convert is not enabled by default. You'll need to make sure the following lines exist in your .hg\hgrc file (c:\repos\ReallyBigProject\.hg\hgrc in my example):
[extensions]
hgext.convert=
#Nick
"E.g. in Subversion, you might have trunk and branches. If I only want to get trunk (or one of the branches) I can just request [project]/trunk. If I clone the hg repo I'll get trunk and all of the branches. This might be a lot of information I don't want. Can I avoid getting this?"
Absolutely. Just use hg clone -r <branch> and get only the branch you want. If you have lots of branches, you need a -r <branch> for each one. <branch> doesn't have to be a named branch: you can simply have multiple unnamed heads (or named heads using bookmark, though those still aren't perfect, because currently they don't show up with push/pull/clone).
Keep in mind that in DVCSes, Mercurial among them, branches are often short-lived and merged back into each other frequently. If you pull a branch you will still get the common history it has with any other branches.
To my knowledge, that's not possible. But compared to Subversrion, cloning the whole repos may not be slower than just a branch from SVN.
Quoting from UnderstandingMercurial:
Many SVN/CVS users expect to host
related projects together in one
repository. This is really not what hg
was made for, so you should try a
different way of working. This
especially means, that you cannot
check out only one directory of a
repository.
If you absolutely need to host
multiple projects in a kind of
meta-repository though, you could try
the Subrepositories feature that was
introduced with Mercurial 1.3 or the
older ForestExtension.
#Nick said:
"This is a pretty big omission since a lot hosting sites only offer one repo. With svn I can effectively have as many repos as I want by only taking one branch from the main one. The subrepos sound like a hack."
Subrepos (aka submodules) are not as ideal as "narrow clones" its true. But at least for having many distinct projects in one hosting site's repository, you can have multiple code-bases in one repository. This won't allow you to slice up different sections of one repository / sub-directories of a project , but it will let you manage multiple projects. What you do is have lots of named branches each rooted at the empty (or null) changeset (i.e. they have no common root revision). It can get a little messy to track the branches but it does work.
For example:
hg init
hg branch project-1
# Changes, commits, repeated as needed
hg update null
hg branch project-2
# Changes, commits, repeated as needed
You now can see all your projects:
> hg branches
project-2 5:42c2beffe780
project-1 2:43fd60024328
The projects are unrelated (though you can merge them):
> hg debugancestors
-1:000000000000
Most usefully: you can clone only the project you want, and the others won't mix in:
> hg clone <repository> -r project-1
The graph for this would look something like this (hg log -qG):
# 5 | project-2 | {tip}
|
o 4 | project-2
|
o 3 | project-2
o 2 | project-1
|
o 1 | project-1
|
o 0 | project-1
You can do this for as many projects as you need, listing each with hg branches, and jumping between them with hg update. This takes some care, because named branch support isn't perfect. It isn't always intuitive for one thing (read about hg clone -u in Mercurial 1.4 -- the pre-1.4 behavior is surprising when cloning). But it does work.
Mercurial and Git only permit cloning on the entire repository. Thus it is recommended that each project gets its own repository.
Mercurial has a forest extension to ease having a "forest" for project repositories. The extension keeps each project in a separate repository, but provides options to update/push/pull all the forest repositories together.
It's possible to ask Mercurial to clone just a branch using hg clone -r branchname (see Mercurial clone from a branch).
With Google's NarrowHG extension extension it's possible to perform a narrow clone (see How do I clone a sub-folder of a repository in Mercurial? for a similar question).
I know that it is nearly 10 years after this question was asked, I I stumbled across
this question by accident.
There is a new mercurial extension call sparse that allows you to do this.
Here's a possible improvement to Vadim Kotov's solution that supports spaces in the small-project name/subfolder:
#echo off
echo Converting "%~1"
REM Create the file map
echo include "%~1" > ~myfilemap
echo rename "%~1" . >> ~myfilemap
REM Run the convert process
hg convert --filemap ~myfilemap .\ "..\%~1"
REM Delete the file map
del ~myfilemap
cd ".\%~1"
REM update the new repo--to create the files
hg update
Is there a way to remove a from a remote changeset, or to remove an entire changeset?
I accidentely pushed a .war file to a remote repo and I want to remove it.
Mercurial tries very hard to keep your data safe, so you can generally not change history.
That being said, there are numerous extensions for Mercurial that allows you to quite easily change history anyway. There is a page on the wiki about editing history. That page also explains the consequences.
In your specific case, you have to ask yourself if others will have already pulled your changeset? If so, then even if you remove it, it will still exist in their clones and you might be better off with accepting the mistake.
If you decide to remove it, I suggest using hg clone to get a copy without it. This is the safe way since it will always leave behind a backup. If you pushed [z] to the remote repository:
[x] --- [y] --- [z]
and now want to remove it, then log into the server and do
hg clone -r y repo repo-without-z
Then repo-without-z will contain all changests up till [y] — that is, [z] will have been removed:
[x] --- [y]
You can then continue working and push a new changeset:
[x] --- [y] --- [w]
If I had pulled the [z] changeset already and now pull [w] I will see two heads in the repository:
[w]
/
[x] --- [y] --- [z]
This is not dangerous per se -- but people might be surprised. If I remove [z] from my clone I will end up with the same repository as you. But, as wrote above, this might be impractical if you have many users.
You can also use the MQ extension to strip the changeset away in-place. That way you wont make a new clone.
Finally, if you're certain that the push was the very last operation done on the server, then hg rollback can be used to remove the last transaction. But don't do this if you are the only one who can push to the repository, otherwise you might end up rolling back a different transaction.
If the repository is on Bitbucket, then you cannot log into the server. But Bitbucket has recently added a strip functionality to its web interface. Look for "Repository management" in the "Admin" section.
Bitbucket does offer you a bundle (backup) upon stripping, and this does not count against your quota. The reason why it appears to do so, is only because we haven't invalidated the cache key specifying how much space you use.
This is a bug in our system, and will be remedied. Until then, rest assured that the changeset has been removed, and the backup is free :-)
I used hg mqueue extension to edit history. It seems that it worked.
Thanks all.
I had a similar case where i want to remove a merged branch "A" changeset from "Dev" branch remotely using TortoiseHg:
Create branch AA from branch A's parent branch; its origin.
Merge A into AA (working directory) and make sure that option: "Discard all changes from the other revision" is checked.
Merge AA into Dev branch (with a commit message indicating that branch A changes were removed).
You'll see that branch A changes are no longer exist in Dev.