I use a bookmark based development approach and have various scripts written to help me do this. I'd like to run one of these scripts after updating to a new bookmark. I've added an update hook, but this seems to run before the bookmark has been changed:
$ hg update new-bookmark
$ <SCRIPT RUNS>
$ (activating bookmark new-bookmark)
How do I add a hook which will run after the current bookmark has been updated?
Your testing just wrong. update-hooks performed after new changeset become active
Test-case
>hg log -T "{rev}:{node|short}\n"
2:e37c7be131f2
1:ef24a87ada3d
0:a8219c43c17e
Hooks section of repo's .hgrc
[hooks]
update.UpHook = echo Update hook: && hg id -in
preupdate.preUpHook = echo PreUpdate hook: && hg id -in
Testing
>hg id -in
a8219c43c17e 0
>hg up 2
PreUpdate hook:
a8219c43c17e 0
Update hook:
e37c7be131f2 2
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
Related
I accidentally did a "hg commit --amend" instead of just a commit. How can I roll back the commit to before the amend?
You can use hg reflog (from the journal extension) and hg reset <hash>.
hg reflog -v
should give something like:
<old-hash> -> <new-hash> <user> <timestamp> commit --amend <some-path>
if that is the amend you want to revert, just use:
hg reset <old-hash>
The commit will be reverted to what is previously was and the changes that were amended should now be uncommitted changes (check using hg status and hg diff).
If your version of Mercurial is new enough, I believe you should be able to use the hg unamend command from the uncommit extension that ships with Mercurial. This may require that obsolescence markers are enabled, I'm not sure.
Enable the uncommit extension, add this to your ~/.hgrc:
[extensions]
uncommit =
Actually run the unamend:
hg unamend
Find the latest saved backup in .hg/strip-backup directory
hg unbundle .hg/strip-backup/<latest backup>
Now you should have two heads - one with the amended commit, other one with two commits (first one - old commit before amending, second one caled: "temporary amend commit for (old commit hash)".
if you have histedit extension, you can do hg histedit on it in order to change it (e.g. select edit in order to achieve a state just before the commit, i.e. when you can see all changes using hg diff).
Don't forget to strip the old head.
It's 2022, and my attempts to use hg unamend have not worked. histedit is too clunky for my purposes, but the solution proposed by mariu52 elsewhere on this page can easily be adapted to work without histedit. It relies on the -k option of the strip subcommand.
In a nutshell:
Find the latest saved backup in the .hg/strip-backup/ directory
Run hg unbundle .hg/strip-backup/<latest backup> where <latest backup> signifies the full filename.
Run hg heads and note the rev number corresponding to the amendment.
Let's call this $AMENDREV; this is the rev number we will strip in the next step.
Run hg strip -k --rev $AMENDREV
Using the -k option in the strip command is critical.
WARNING: this procedure will in effect erase the memory of any add or remove commands
that were pending when the amend command was executed.
For example, in the transcript below, the hg add file2 command is effectively
forgotten after the strip command is executed.
For clarity, here's a transcript based on the above recipe.
$ mkdir tmp ; cd tmp
$ ls
$ echo 1 > file1
$ echo 2 > file2
$ hg init
$ ls
file1 file2
$ hg add file1
$ hg commit -m 'one file'
$ hg add file2
$ hg amend -m 'amendment'
saved backup bundle to /tmp/tmp/.hg/strip-backup/d332ee829c21-5a5f23b0-amend.hg
$ hg unbundle -u .hg/strip-backup/d332ee829c21-5a5f23b0-amend.hg
adding changesets
adding manifests
adding file changes
added 1 changesets with 0 changes to 1 files (+1 heads)
new changesets d332ee829c21 (1 drafts)
0 files updated, 0 files merged, 0 files removed, 0 files unresolved
updated to "1a445f3252eb: amendment"
1 other heads for branch "default"
$ hg heads
1[tip]:-1 d332ee829c21 2022-11-09 01:55 -0500 peak
one file
0 1a445f3252eb 2022-11-09 01:55 -0500 peak
amendment
$ ls
file1 file2
$ hg strip -k -r 0
saved backup bundle to /tmp/tmp/.hg/strip-backup/1a445f3252eb-bfaab5ec-backup.hg
$ ls
file1 file2
$ hg list
r0: peak tip 2022-11-09 01:55 -0500
one file
file1
$
hg unamend part of Mercurial 4.5 (2018-02-01).
NOTE: This answer is now deprecated. See the answer from #Sorina Sandu instead.
See hg help commit, where it says:
The --amend flag can be used to amend the parent of the working
directory with a new commit that contains the changes in the parent in
addition to those currently reported by "hg status", if there are any.
The old commit is stored in a backup bundle in ".hg/strip-backup" (see
"hg help bundle" and "hg help unbundle" on how to restore it).
I have mercurial repository, and by providing the URL to Jenkins, i get the following in stdout:
Started by an SCM change
[workspace] $ hg incoming --quiet --bundle hg.bundle --template "{desc|xmlescape}{file_adds|stringify|xmlescape}{file_dels|stringify|xmlescape}{files|stringify|xmlescape}{parents}\n" --rev default
[workspace] $ hg unbundle hg.bundle
adding changesets
adding manifests
adding file changes
added 1 changesets with 1 changes to 1 files
(run 'hg update' to get a working copy)
[workspace] $ hg update --clean --rev default
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
[workspace] $ hg log --rev . --template {node}
No emails were triggered.
Question is HOW are these commands generated and can they be modified ?
Those commands are part of the Mercurial Jenkins plugin, with the source code available at GitHub.
You can find the incoming command used in the hudson.plugins.mercurial.MercurialSCM.java class in the update() method.
os.write("<changesets>\n".getBytes());
ArgumentListBuilder args = findHgExe(build, listener, false);
args.add(forest ? "fincoming" : "incoming", "--quiet");
if (!forest) {
args.add("--bundle", "hg.bundle");
}
args.add("--template", MercurialChangeSet.CHANGELOG_TEMPLATE);
args.add("--rev", getBranch(env));
In our repository we have initial version of database (binary file).
I have executed hg pull and I saw that someone committed another version of this file.
As I won't to loose my changes in dev db, I did make a copy of it (copy file.db my_file.db) in same directory.
When I runned hg up, mercurial overwrited file.db with new version and deleted my_file.db!
I'm on windows 7 x64, and tried various software that recover deleted files, but with no success.
How can I get back my version of file.db or recover my_file.db? I didn't commit it.
I really don't think mercurial deleted your untracked file. Here's the sequence you've described as I understand it:
ry4an#four:~$ mkdir zote
ry4an#four:~$ cd zote
ry4an#four:~/zote$ hg init orig
ry4an#four:~/zote$ echo text > orig/file.db
ry4an#four:~/zote$ hg -R orig commit -A -m 'initial'
adding file.db
ry4an#four:~/zote$ hg clone orig clone
updating to branch default
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
ry4an#four:~/zote$ mv clone/file.db clone/my_file.db
ry4an#four:~/zote$ echo more text >> orig/file.db
ry4an#four:~/zote$ hg -R orig commit -m 'new line'
ry4an#four:~/zote$ hg -R clone pull
pulling from /home/ry4an/zote/orig
searching for changes
adding changesets
adding manifests
adding file changes
added 1 changesets with 1 changes to 1 files
(run 'hg update' to get a working copy)
ry4an#four:~/zote$ hg -R clone update
remote changed file.db which local deleted
use (c)hanged version or leave (d)eleted? c
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
ry4an#four:~/zote$ ls clone/
file.db my_file.db
ry4an#four:~/zote$ cat clone/my_file.db
text
ry4an#four:~/zote$ hg -R clone status
? my_file.db
You can see that afterward my_file.db is still there. Even with --clean as Mikezx6r mentiones the file is still there:
pulling from /home/ry4an/zote/orig
searching for changes
adding changesets
adding manifests
adding file changes
added 1 changesets with 1 changes to 1 files
(run 'hg update' to get a working copy)
ry4an#four:~/zote/clone$ hg update --clean
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
ry4an#four:~/zote/clone$ ls -l
total 8
-rw-r--r-- 1 ry4an ry4an 15 2011-02-08 14:31 file.db
-rw-r--r-- 1 ry4an ry4an 5 2011-02-08 14:28 my_file.db
ry4an#four:~/zote/clone$ hg stat
? my_file.db
ry4an#four:~/zote/clone$
It's not what you want to hear, but it's much more likely you accidentally botched the 'mv' and only thought you created the copy or somehow externally deleted it. Or your antivirus app saw a pattern it didn't like a refused to create it, or some other horrible, accidental thing.
It's also not helpful now, but this is a great example of why you should commit early and often, and especially before updating -- it's just too easy to make mistakes, but once something in in the repo there's nothing you can do to accidentally remove it.
Is there a Mercurial command you can use after an hg pull to see a list of all files that will be need to be manually merged (ie: that have conflicts) when doing an hg merge?
hg resolve --list
From the documentation:
Merges with unresolved conflicts are often the result of non-interactive merging using the internal:merge configuration setting, or a command-line merge tool like diff3. The resolve command is used to manage the files involved in a merge, after hg merge has been run, and before hg commit is run (i.e. the working directory must have two parents).
Edit 5 January 2012:
(I received an up vote for this answer today so I revisited it. I discovered that I misunderstood the question.)
The question is "I have performed a pull from a remote repository and have not yet performed a merge. Can I see what conflicts will be created upon performing the merge?"
My answer above is clearly wrong. After reading through the linked documentation, I do not think there is a built-in method for doing this. However, there is a way to do it without ruining your working source tree.
Let's assume you have cloned repository A from some remote source to repository B on your local system, i.e. hg clone http://hg.example.com/A B. After doing so, you make changes to your local repository, B, that involve at least one commit. In the meantime, changes have been made to repository A so that when you do a pull you get a message indicated new changesets have been added and heads have been created.
At this point, you can do hg heads to list the two changesets that will be involved in a merge. From this information, you can issue a status command to list the differences between the heads. Assuming the revision numbers in your repository B, according to the heads list, are "1" and "2", then you can do hg status --rev 1:2 to see a list of the changes.
Of course, this doesn't really tell you if conflicts will occur when you do a merge. Since there isn't a command that will show you this, you will have to "preview" the merge by cloning to a new repository and doing the merge there. So, hg clone B C && cd C && hg merge. If you are satisfied with the result of this merge you can do hg com -m 'Merging complete' && hg push && cd ../ && rm -rf C.
It's a bit of a process, but it keeps your current source tree clean if the merge turns out to be a disaster. You might also find this description of working with public repositories helpful.
Unless I'm misreading it myself, the answers above don't seem to address the question that I think is being asked: I have two branches in my repository that I'd like to merge, and I want to know what conflicts will come up (e.g., before stepping through the conflict resolutions one-by-one.)
To do this, I would merge with the :merge3 tool (which tries to merge automatically, but leaves conflicts unresolved) and then use hg resolve --list — or just look at the output of merge command — to see the conflicts.
hg merge <otherbranch> --tool :merge3
hg resolve -l
If you didn't actually want to merge in the end (if you just want to see what would conflict) you can run hg update -C afterwards to undo the merge.
If you do want to finish the merge, you can run hg resolve <filepath> for each file, or just hg resolve --all to step through all that remain with conflicts, before you hg commit the merge changeset.
You can use the --rev option of hg stat with a pair of revisions to see what file differences exist between the two. See below for a slightly verbose but detailed example:
First we start by making a new repository:
[gkeramidas /tmp]$ hg init foo
[gkeramidas /tmp]$ cd foo
Then add a single file called foo.txt to the new repository:
[gkeramidas /tmp/foo]$ echo foo > foo.txt
[gkeramidas /tmp/foo]$ hg commit -Am 'add foo'
adding foo.txt
[gkeramidas /tmp/foo]$ hg glog
# 0[tip] b7ac7bd864b7 2011-01-30 18:11 -0800 gkeramidas
add foo
Now add a second file, called bar.txt as revision 1:
[gkeramidas /tmp/foo]$ echo bar > bar.txt
[gkeramidas /tmp/foo]$ hg commit -Am 'add bar'
adding bar.txt
Go back to revision 0, and add a third file, on a different head. This is done to simulate a pull from someone else who had cloned the same repository at its starting revision:
[gkeramidas /tmp/foo]$ hg up -C 0
0 files updated, 0 files merged, 1 files removed, 0 files unresolved
[gkeramidas /tmp/foo]$ echo koko > koko.txt
[gkeramidas /tmp/foo]$ hg commit -Am 'add koko'
adding koko.txt
created new head
[gkeramidas /tmp/foo]$ hg glog
# 2[tip]:0 e5d80abdcb06 2011-01-30 18:12 -0800 gkeramidas
| add koko
|
| o 1 a2d0d0e66ce4 2011-01-30 18:12 -0800 gkeramidas
|/ add bar
|
o 0 b7ac7bd864b7 2011-01-30 18:11 -0800 gkeramidas
add foo
Now you can use hg stat to see what file differences exist between any pair of revisions, e.g. the changes from rev 0 to rev 1 added 'bar.txt' to the file list:
[gkeramidas /tmp/foo]$ hg stat --rev 0:1
A bar.txt
The changes from rev 0 to rev2 added 'koko.txt' to the file list:
[gkeramidas /tmp/foo]$ hg stat --rev 0:2
A koko.txt
But more interestingly, the changes from rev 1 to rev 2 involve two file manifest changes. (1) 'koko.txt' was added in rev 2, and (2) 'bar.txt' exists in rev 1 but is missing from rev 2, so it shows as a 'removed' file:
[gkeramidas /tmp/foo]$ hg stat --rev 1:2
A koko.txt
R bar.txt
I think hg status is what you are looking for.
You may want to read this chapter from Mercurial: The Definitive Guide
http://hgbook.red-bean.com/read/mercurial-in-daily-use.html
How can I alter r0 so it looks like I added .hgignore when I created my repository or insert a commit before my current r0?
I just converted a huge SVN repo using hgsvn to mercurial. It took several hours and had to go through about a dozen branches to get the whole thing. My problem now is that .hgignore isn't committed, so when I hgimportsvn a branch, the .hgignore doesn't seem to come with it. I would like to insert that file as part of r0 or insert it before that (and shift everything by 1). I've also tried committing it at the end of my Mercurial trunk checkout, but it seems hgimportsvn always clones (branches?) from the same Mercurial revision my SVN branch was created from so .hgignore is lost again.
You probably need something like the ConvertExtension. Check out the --splicemap option.
To create a new history with a .hgignore file added as the first revision:
Create a new repository whose only revision is the .hgignore commit.
Create a splicemap file containing two 40-char hashes: rev 0 of your current database, and rev 0 of your new database.
Run hg convert <current_db_dir> <new_db_dir> --splicemap splice_filename
This adds each revision in the current database to the new database. The splicemap specifies editing of parents, so if revision 0 of the current database gets its parent set to revision 0 of the new database.
Below is a Windows batch file that creates a 3-revision database and a 1-revision database with an .hgignore file in it, the splices them together. The result should be what you are looking for. If you have a large original database it could take a while, since the entire history of the source database is re-written to the destination database.
#echo off
#REM Create a 3-revision database
hg init current
cd current
echo >file1
hg add
hg ci -m file1
echo >file2
hg add
hg ci -m file2
echo >file3
hg add
hg ci -m file3
#REM Add the first revision to the splice map
hg log -r 0 --template "{node} " > ..\map
#REM Display the result
hg log
cd ..
#REM Create a 1-revision database
hg init ignore
cd ignore
echo glob:*.txt>.hgignore
hg add
hg ci -m ignore
#REM Specify this node as the parent of the other
#REM database's first revision in the splice map
hg log -r 0 --template "{node}\n" >> ..\map
hg log
cd ..
#REM Here's the resulting splice map
type map
#REM Make a copy to store the result
hg clone ignore result
#REM Add revisions from "current" to "result" honoring
#REM the splice map
hg convert current result --splicemap map
#REM Display the result
cd result
hg log
Maybe you could commit .hgignore and then rebase the commit to the beginning of history (see https://www.mercurial-scm.org/wiki/RebaseProject).