In mercurial, the merge ignored some files (possibly a human mistake). How I can 're-include' the ignored files?
Scenario: the merge target(rev #47) has 5 files, but the merge(rev #50) has included just 1 file and others are ignored.
Apparently, when I check the resulting code, the code from Rev# 47 is missing.
You probably did the merge in a way you didn't intend, e.g. telling hg to only accept changes from one branch, discarding the changes from the merged rev47.
The easiest way is to start with a repo where the merge did not happen and re-do the merge. This is not possible, if it is a shared repo and that merge is already shared with others. If it everything local, but if that repo is your only copy, make a new clone without the merge: hg clone -r49 OLDREPO .
Thus if you cannot simply re-do the merge on a new repo without that merge, you'll have to go a longer way which is summarized in this answer. Note the screenshot in the accepted answer and DO NOT discard the changes from the merge target.
Related
I have seen Remove file from a commit in Mercurial - but I have very little experience with Mercurial, so I'd like to ask and make sure if this is doable, and how.
There is a software that is developed in Mercurial, and I wanted to try and add a feature. So when I cloned the repo, first I did was added my own branch, and started hacking there. Already in first or second commit of this branch, I added multiple files hg add test1.bmp, hg add test2.bmp and so on, and committed.
Then I kept on hacking other files (haven't touched these test1.bmp, test2.bmp etc since), and made about 3 or 4 commits after the commit where the bmps are added. Nothing has been pushed anywhere - my local copy of the Mercurial repo and my branch in it is the only place where these files are referenced. And just now I realize I shouldn't have added those files at all.
Is it possible to remove these files from all of the commits where they feature, since the first commit where they were added?
Or maybe I should formulate the question in singular - is it possible to remove a file from all of the commits where it features, since the first commit where it was added? (if it is possible for one file, then I can just repeat the process for any additional file I'd like to remove)
Yes this is possible.
However, this is a more advanced use of mercurial and will require you enabling at lease one extension.
As a new user, my recommendations would be to simply use mercurial basic management and remove the file(s) of concern:
hg remove <file>
You can then commit the change.
While this will not remove the file(s) from all changesets, it will remove it
going forward. This honestly is the recommended way of managing working content.
It should be noted that this is likely your only option if you have pushed changes to the parent repository. If you have pushed your changes to the parent repository, you will also have to edit it which makes things much more complicated and the potential for a serious mistake more likely.
If you truly want to remove it from previous changesets, you will need enable the histedit extension (included with mercurial).
[extensions]
histedit =
Since you are a relatively new user to mercurial, I strongly recommend that you backup your repository and experiment there before attempting this on you working copy.
The process I recommend for this is as follows:
Note: this only works as described for changesets that have not been pushed and have phase = draft (or secret)
1) Identify all changes where file(s) are added or modified
You will need to know each changeset where the file(s) where modified or added. You will need to modify each of these changesets in the reverse order that they where added.
You can use:
hg log file
to list changesets where the file was modified or added.
2) Slowly edit each affected changeset (working your way backwards)
Use the histedit to display all show all changesets that can be modified/edited in your default editor.
hg histedit
Find the first changeset you identified and change it from pick to edit and save the change.
This will drop you into histedit edit mode. This is the state just before the changeset was committed. This means you can make changes such as modifying, unedifying. Adding or removing content. In this case we want to undo any changes to the file(s) in question.
hg revert file
or
hg remove file (if this is the changeset where the file as added)
3) recommit changeset
Once you have reversed the file changes/additions, you need to inform histedit
that you are done.
hg histedit --continue
This will cause the changeset to be recommitted with the modifications you made including editing the commit message.
Repeat this for each changeset until completed.
Note: While you can select multiple changes to edit in histedit, I recommend doing one at a time to help reduce complexity. Remember to do the in the reverse order that they where committed to help reduce / eliminate any merge conflicts.
Again a recommend practicing on a repository copy until you have the process firmly understood. Since you are modifying repository history, this can have potential negative effects of a mistake is made.
I highly recommend reading this: https://book.mercurial-scm.org/read/changing-history.html.
I made some changes to a file and committed it. (In fact there were several commits).
Then I wanted to revert to the earlier version and lose all those changes.
I did something like:
hg update -r nnn where nnn was the reversion number of the changeset I wanted to go back to.
That worked. I was happy.
Then, later, I had to push my local repository to the remote. But when I did hg push I got a message about there being two heads on this branch and one of them not being known to the remote repositiory. It suggested I merge before pushing. (I think).
I googled this and found a page that suggested I do "hg merge". I did that. Now the resultant file is back to where I started. I.e. it contains all the changes I wanted to throw away.
Where did i go wrong?
EDIT:
I have found this post Mercurial — revert back to old version and continue from there
where it says:
If later you commit, you will effectively create a new branch. Then
you might continue working only on this branch or eventually merge the
existing one into it.
That sounds like my case. Something went wrong at the merging stage it seems. Was I on the wrong branch when I did "hg merge"?
You're past this point now but if it happens again, and it's just a single file you want to revert then consider:
hg revert --rev REVISION_YOU_LIKED path/to/just/one/file.txt
That doesn't update you whole repository to a different revision, and it doesn't create any commits. It just takes a single file in your working directory and makes it look like it used to. After doing that you can just commit and you're set.
That's not the way to go if you want to undo all the changes you've made to all files, but for reverting a single file use revert and avoid multiple heads and merging entirely.
No, nothing went wrong at the merge stage – Mercurial did exactly what you asked it to...
What merge means is that you take the changes on your current branch, and the changes on the 'other' branch, and you merge them. Since your original changes were in the 'other' branch, Mercurial carefully merged them back into your current branch.
What you needed to do was to discard the 'other' branch. There are various ways of doing that. The Mercurial help pages discuss the various techniques, but there are pointers in other SO questions: see for example Discard a local branch in Mercurial before it is pushed and Remove experimental branch.
(Edit) Afterthought: the reason you got a warning about there being two heads on the branch is because having two heads is often a temporary situation, so pushing them to a remote repository is something you don't want to do accidentally. Resolutions are (i) you did mean to push them, so use --force to create two heads in the remote repository; (ii) ooops!, you meant to merge them before pushing, so do that; or (iii) ooops!, you'd abandoned the 'other' one, so get rid of it. Your case was (iii).
I accidentally renamed a file outside of Mercurial. When I committed the change, Mercurial treated the change as two unrelated files (ie. a remove and a add). I need to go back to diff the two revisions but I don't know how to do so when Mercurial sees them as two respective files across different revisions. What can I do to diff the files?
You didn't say what operating system you were using. The following will work with bash on Linux:
diff <(hg cat -r rev1 file1) <(hg cat -r rev2 file2)
You can replace diff with another program like vimdiff if you want a visual diff.
If you want to actually fix the history so that Mercurial is aware of the rename (and can use that information in future merges if needed), there's a way to do so documented on the Tips and Tricks page on the Mercurial wiki.
Current contents copied here for ease of use (and in case the link gets broken later):
Steps:
Update your working directory to before you did the rename
Do an actual "hg rename" which will create a new head
Merge that new head into the revision where you did the "manual" rename (not the head revision!)
Then finally merge the head revision into this merge result.
Advice:
Make a clone first and work on that, just in case!
After finishing the steps, use a file compare tool to check that the original and the clone are identical
Check the file history of any moved file to make sure it is now restored
That being said, if all you want to do is compare the contents at the point in time, you can definitely accomplish that without making Mercurial aware of the rename (as mentioned in Stephen Rasku's answer). In fact, you can use a combination of "hg cat" and an external comparison tool to compare any files, not just ones that Mercurial knows about.
Fix history:
Update to first changeset with new-filename, save file outside WC
Update to parent of bad replacement changeset, replace file correctly (with rename tracking), commit, got second head
Rebase all changesets from old anonymous branch on top of fresh good changeset
--close-branch on bad-replacement changeset or delete this unwanted changeset or leave inactive head intact
I'm in my branch, and I do this:
hg incoming /path/to/baseline
And I get a few changesets in the output.
Now do I just merge to pull in the changsets to my branch?
hg merge /path/to/baseline
Will my history show what was merged?
As long as I didn't touch those files, it will be automatic right?
You should really try all this out yourself! Make a couple of test repositories:
hg init main
hg clone main clone
and then experiment away. It's easy and safe since you're only playing around on your own machine. (This is actually what happens "behind the scenes" when you ask a question here: I try to make sure that the advice I give really works, so I normally have to run a few tests on a new repository to double-check.)
If you ran the tests, you would see that
You cannot give hg merge a path name (or URL) as argument. It takes a revision as the only argument. You need to hg pull /path/to/baseline to copy the changesets into your local repository and then hg merge.
The history will indeed show what was merged. A merge becomes a merge commit in Mercurial. That is a changeset with two ancestor changesets — both lines of development leading up to the merge are still in the repository.
Merges are without conflicts ("automatic") if the changes made in the two branhces don't overlap. If you edit different files in the two branches then there's certainly no overlap. But you can also edit different regions within the same file and still have a merge without conflicts.
There is a fine tutorial on the wiki and I've also written a beginners guide. I hope that helps.
Is it
pull
update
merge
commit
push
? Or can you do the commit first?
I don't like the idea of pulling and merging without having a version of my local code backed up somewhere in case the merge explodes, but presumably you have to do the merge before you can do a push, because you can't have conflicts in the central repo. Not quite understanding this whole process yet; used to my nice simple SVN.
I recommend to always commit before pulling in changes to your working directory, unless you are 100% sure that your changes and the changes to be merged into your working directory will not conflict.
If you do an updating pull (hg pull; hg update, or shorter hg -u pull) and have any outstanding non-committed changes, any changes coming from outside will be combined with your changes. When conflicts happen, it might be difficult to decide how the merge result should look like, because you can't easily distinguish between your changes and the changes merged in.
When you did commit first, it is much easier to decide how the merge result should look like, because you can always look at both parents of the merge.
So, in effect it is:
hg commit
hg pull -u (if no merge necessary, go to 5)
hg merge
hg commit
hg push
Update: As Martin Geisler has pointed out, it is possible to get at the "original" changed version of a file using:
hg resolve --unmark the-file
hg resolve --tool internal:local the-file
or for all files at the same time:
hg resolve --unmark --all
hg resolve --tool internal:local -all
Still, I find the "commit first" system nicer. At the end, it is personal preference...
I don't know as there's a standard per se, but one of the ideas behind Mercurial is that you can commit as often as you like since it goes to your local repository. So you can commit to your heart's content as much as you like before you pull updates.
I tend not to commit very often, saving up for when I'm preparing to push, but that's me. I can see the utility of committing early and often. I do pull updates frequently as I work to cut down on merge fun.
One other thing I do is to keep a parallel clone of my working repo (cloned from the same repository as my working repo, not cloned from my working repo) so that I can check the original state of a file easily, and if need-be check in an out-of-band emergency fix or what-have-you without complicating my current change set.
Do edits
Commit
Goto 1 until satisfied
Pull
Merge & commit
Push if you want to.
Definitely commit before trying to do something complex like a merge. I don't think mercurial will allow you to merge before committing, but even if it did, what if the merge goes wrong. You have no pre-merge revision to go back to.
Commit early, commit often.
If you don't, you are missing out on a huge benefit of a DVCS.
but presumably you have to do the merge before you can do a push, because you can't have conflicts in the central repo
Wrong statement and poor understanding of distributed workflow and parallel development.
You can merge heads before push, but not have or must. Push can put any data to repo, if it needed and intended to be so
By default, push will not allow creation of new heads at the destination,
since multiple heads would make it unclear which head to use. In this
situation, it is recommended to pull and merge before pushing.
(NB: "recommended to pull and merge before" statement)
You can use commit-pull-merge, stash-pull-unstash-merge, perform fetch with modified WC and merge on the fly, don't merge heads at all or sporadically and push --force with +1 heads - there are not common rule for everybody. And any and every such workflow doesn't produce "conflicts in the central repo", but only different DAG.
Each point of divergence, which appear in case of existing your and other changeset from commmon parent in your (or even central) repo is a point of starting anonymous branches in Hg, which (technically) are absolutely legal, applicable and usual way. How they handled is defined by policy and agreement between developers, PM, QA-team and others
I, personally, prefer finish my task (in one or more amount of commits), after it pull and maybe merge, when it approved by development-policy