Many times I'm making two different changes to files in my repository, I want those changes to be treated as two consecutive commits.
For example, in repository
prog.c
prog.h
README.txt
While fixing a bug prog.c and prog.h, I fixed a typo in README.txt. Now I want to commit the change to prog.c with its own commit message, and the change to README.txt afterwards.
In git, I could easily do that with the index
git add prog.c prog.h
git commit -m 'bug #1234'
git commit README.txt -m 'some typos fixed'
What's the best way to do that in Mercurial?
Clarification: I used (before the edit) a toy example where each changeset spans over a single file. But I want the general answer, what should I do when there are many files in each changeset.
hg commit -m "bug #1234" prog.c prog.h
then
hg commit -m "some typos fixed" README.txt
I LOVE the crecord mercurial extension for this purpose: it gives me file by file (and chunk by chunk, and line by line) control over what exactly I want in this commit.
Related
I'm trying to commit my project using git commit -m "First.". But throw this error, remembering that I wrote git init.
Other version control systems simply commit whatever files have been changed. Git is different. You must first build the commit by adding them to the staging area with git add. Then you git commit what has been added. This allows you to do some very powerful things, like split big changes into multiple commits.
For the above, add everything with git add . then you can commit. Though you probably want to add .vscode, tmp/, *.lock and any other temporary files and directories to your .gitignore file.
For more, please read Git Basics - Recording Changes to the Repository.
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
Suppose I have two branches A and B. These two branches have been merged together outside of hg (manually I suppose). The merge itself is correct and the files exactly reflect the merge between branch A and B.
Is there a way to commit those files as a merge? I mean to make them appear in hg as if they were merged using hg and make the new commit have both branches as a parent?
One option is to do the merge, but tell hg that you really want that merge to fail. Then reset the files to the version you want and manually mark them as resolved.
hg -y merge --tool=internal:fail otherBranch
hg revert --all --rev thisBranch
hg resolve -a -m
Once you commit and you should be on your way.
See more details here
Let's say you do hg status and you have three files modified. I know how to check in all three files (hg commit). But how can you check in (and then hg push) just one of the modified files?
Please check the output of hg help commit which reveals that you can do
hg commit foo.c
if you just want to commit a single file. This is just like Subversion and many other systems — no hocus-pocus :-)
Just do:
hg ci -I path/to/file -m "commited only one file"
That commits only one file, and you can push it, and none of the uncommitted changes will be affected.
On the off chance you're running on Windows, TortoiseHG (a graphical Mercurial interface) lets you select which files to commit every time.
When I have two branches in Hg repo, how to merge only one file with another branch, without having all other files from changeset merged?
Is it possible to merge only certain files, instead of whole changeset?
WARNING: a "dummy merge", as is recommended by #Martin_Geisler, can really mess you up, if later you want to do a true merge of the two branches. The dummy merge will be recorded, and say that you merge into the branch you did the dummy merge to -- you will not see the changes. Or if you merge into the other branch, the changes on that other branch will be undone.
If all you want is to copy an entire file from one branch to another, you can simply do:
hg update -r to-branch
hg revert -r from-branch file
hg ci -m 'copied single file from from-branch to to-branch
If you want to select different parts of that file, then "hg record" is useful.
I just did this on my home directory .hgignore.
If both branches have made changes to a file that you want to keep, a dirty trick would be to create a merge of the two branches using hg merge, possibly/probably on still another branch, check that in, and then copy a single file between the merge and the to-branch:
hg update -r to-branch
branch merge-branch
hg merge -r from-branch
hg ci -m 'temp merge to be discarded"
hg update -r to-branch
hg revert -r merge-branch single-file
hg ci -m 'merged single-file from from-branch to to-branch"
hg strip merge-branch
It is worth mentioning: the way to "copy a single file between branches" (or revisions, or from revision to merge, or....) is "hg revert". I.e.
hg update -r Where-you-want-to-copy-to
hg revert -r Where-you-want-to-copy-from file-you-want-to-copy
...
hg ci
For some reason I, and some of my coworkers, find this VERY confusing. "revert"=="copy" ... makes sense for some usage patterns, but not all.
Nope. Mercurial works on a changeset basis.
But you can do a "dummy merge" where you ignore the incoming changes from one of the branches. Before you commit you could then revert selected files to whatever state you want:
% HGMERGE=internal:local hg merge # keep my files
% hg revert --rev other-branch a.txt # update a.txt to other branch
% hg commit -m 'Dummy merge to pick a.txt from other-branch.'
Maybe that will help you a bit.
One fairly clean way of getting the desired result is to do it in two steps: first use graft, then second use histedit.
Say this is the starting point and you need to select some portions of C and D to "merge" after E:
A---B---C---D
\
-E
Then you would graft C and D on top of E:
A---B---C---D
\
-E--C'--D'
Then use hg histedit to edit C' and D'. During the edit you can make any changes you want, but in this case you would just revert any unwanted files, (or even portions of them).
(Note that histedit edit works by temporarily updating your working folder to match the content of the given changeset as though it were not committed yet. So you can easily revert unwanted files and then hg histedit --continue which will effectively replace the edited changeset.)
So the final result would be:
A---B---C---D
\
-E--C''--D''
Where the '' revisions were modified as required.
I would say this approach is more beneficial when you have large changesets that probably should have been multiple smaller commits in the first place; this approach allows you to "disentangle" only the parts that you need. Using this for just a single file would be fine but could be overkill.
I would just use an external tool like vimdiff to diff the two files that I want to merge and then merge them. The advantage of this is that you can do selective editing on parts of the file. E.g:
hg update -r branch-merging-to
hg extdiff -p vimdiff -r branch-merging-from file-I-am-merging
To do this you need to enable the external tools in your .hgrc, which just means adding these lines:
[extensions]
hgext.extdiff =
If you are using an IDE:
Merge the old branch with new branch
Go inside the the IDE and remove the unwanted changes
Generate the diff file
Update and clean the new branch
Apply the diff in the new branch