mercurial: including precommit-changed file - mercurial

On commit to repository I have a hook defined in Mercurial:
[hooks]
precommit.exportDB=exportDB.bat
This creates/updates a SQL-dump from my database, which should be included in the commit.
BUT: although this works, the Sql is marked as new, but not part of the now commiting changeset.
How can I automatically include it so it gets into the set of changed files?
Hope this makes sense...
Thx
Reinhard

This'll sound crazy, but you can do it in two steps. First change your precommit hook to a pre-commit hook -- yup, both exist and they're different. Without the dash the commit has already started and some lock has been acquired. With the dash it happens before the commit starts and you can still hg add the new file.
On a unix like that total change would be:
[hooks]
pre-commit.exportDB=exportDB.sh && hg add resulting.sql
presumably there's something similar on Windows, or you could make the hg add the last line of the batch file.
P.S. Don't commit generated files. :)
Update:
I just tested this and it works as I suggested:
ry4an#four:~$ hg init reinhard
ry4an#four:~$ cd reinhard/
ry4an#four:~/reinhard$ vi .hg/hgrc
ry4an#four:~/reinhard$ cat .hg/hgrc
[hooks]
pre-commit = hg add otherfile
ry4an#four:~/reinhard$ echo text > afile
ry4an#four:~/reinhard$ echo more > otherfile
ry4an#four:~/reinhard$ hg add afile
ry4an#four:~/reinhard$ hg status
A afile
? otherfile
ry4an#four:~/reinhard$ hg commit -m 'message'
ry4an#four:~/reinhard$ hg status --all
C afile
C otherfile
Notice that before the commit only 'afile' is added and 'otherfile' is unknown, and after the commit both files are 'C' (meaning "Clean' -- they've been added and committed).

Related

hg merge says outstanding uncommitted changes; hg commit says nothing changed -- how to exit the loop?

The problem here is that hg' workflow apparently leads in a circle:
hg pull, get another head
hg merge, get warned of outstanding
uncommitted changes
hg commit -m "pre merge commit", get message
saying nothing changed
go to 2 hg status, see output like the
following:
! #foo.py#
? junk.out
? junk2.out
If foo.py is in your list of .hg-ignore'd files try specifying it explicity on the command line when you commit.
e.g.
hg commit -m "commit message" ./#foo.py
edit: looking more closely at your error: the file has been deleted (! in the status list), but hg hasn't tracked the deletion. You need to tell hg about the deletion using:
hg rm -A ./foo.py
The -A / --after means record the removal after it actually occured

Mercurial: roll back an "hg commit --amend".

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).

How to undo "hg qnew"?

I issued hg qnew without realizing that it includes any outstanding changes into the patch. I'd like to back that out and pick only specific changes using hg qrecord. How can I undo qnew?
Your answer definitely works — with newer Mercurial's you can use hg strip --keep to avoid doing the import step:
$ hg strip --keep .
$ hg qdelete patch-name
The --keep flag makes strip ignore the working copy while working, that is, it deletes the commit (like hg qpop would do) but it doesn't undo the changes to the files. After stripping you still have the patch in your series (unapplied) and you can then delete it.
I've found an anwer here:
hg qpop
hg import --no-commit .hg/patches/patch-name
hg qdelete patch-name
Please add a better way, if you know.
Update: Based on Aldo's answer, there is another way:
hg qnew test
# We can undo the above qnew as:
hg qrefresh -X '*'
hg qpop -f
hg qdelete test
If you just want to undo the latest qnew retaining all your local changes, one option is:
qcrefresh 123
hg qpop -f
hg qdelete <name of the patch>
Notice that 123 is just a random string: you are telling mercurial to only include the (hopefully nonexistsnt) 123 file in the current patch.
Newer versions of Mercurial When you issue will issue a warning about the fact 123 file does not exist, but this is exactly what we want here.
If you want to retain some of the changes in the current path, you can use the qcrefresh command from the crecord extension, which allows to graphically select the changes to be included in the current patch. You need to download it from Bitbucket, extract the archive and configure it in .hgrc:
[extensions]
crecord = <path/to/crecord/package>

Mercurial Unstage Specific Files from Working Directory

I have an uncommitted changeset. I want to commit some of the changes, but not commit some of the files (like unstaging a file in git). Can this be done in mercurial?
Use the -X option to hg commit to exclude certain files. You can specify it more than once on the command line. For example,
hg commit -X path/to/unwanted/file -X path/to/another/file
You can pass a list of files to commit to hg commit, e.g. hg commit -m msg file1 file2 ....
Yep! You have two options.
Commit just some files.
If you provide file names as arguments to hg commit, only those files will be committed. So if I have the following hg status:
M foo.txt
M bar.txt
I can run hg commit foo.txt to commit just the changes to foo.txt and leave the changes in bar.txt for a later commit.
Use the record extension.
The Record extension gives Mercurial behavior to git's index, letting you commit just some patches of your changes (like git add --patch). See the docs for more info.

"hg commit" - nothing happens!

I just started my first Mercurial project.
I did a 'cd' into my source directory.
Then I did this:
hg init myproject
But next I did
hg commit -m "first commit"
And all it reports is:
nothing changed
But when I do
hg status
It lists all of the source code in my project.
What am I doing wrong here?
I think the output of the hg status command is probably telling you that you have a lot of files in your working directory that are not being tracked by Mercurial. You should be able to fix this by running the command
hg addremove
Then you can make your first commit:
hg commit -m "first commit"
Alternatively, you can do this all in one command with
hg commit -A -m "first commit"
Try hg push then refresh the repository some times It changes inspite of saying nothing changed