Hg select file based on status? - mercurial

Is there a way to select only those files that have the Modified status?
And is it possible to chain the selection to add more specific selectors?
I want to export the changes in those Modified files, revert to a changeset before I installed the plugin, and re-import changes.
hg diff -I with pattern matching could help, but in this case, and very often, I just want to select files based on their status.
Example of hg st (actual content varies with different folder and filenames/extension):
M /readme.txt
M /dir1/somefile1.txt
M /dir2/somefile2.txt
M /dir3/somefile3.txt
M /dir4/somefile4.txt
! /plugin/lotsoffileshere.txt
! /plugin/lotsoffileshere.txt
! /plugin/lotsoffileshere.txt

Read about filesets in mercurial: hg help filesets
If you want get diff for all modified files (hg diff FILE1 FILE2 ... FILE), build filest for "modified files in repo" in will be (only help was used)
hg diff "set:modified()"

Related

Generating a list of directories containing files changed between revisions

I know from this answer that I can do
hg status --rev x:y
to list files that have been changed between revisions x and y. Is there a way to get not the indiviual files but only the directories in which they are contained?
For example if the above command would yield
A Foo\Bar\SomeFile.txt
A Foo\Bar\AnotherFile.cs
M Baz\AnotherFile.txt
I want to get
Foo\Bar
Baz
instead.
Not a ready-to use solution (see end-notes), just hints
You can use templates for changing output format of hg st, as it can done for any "log-like" hg commands (see -T option)
in template you can filter output (filenames) with filter "dirname", which'll strip filename part of file
but I tried it and discovered (on my repos) some "oddities" (and expected troubles)
End-notes:
While default output of hg st eliminates duplicate filenames (if they appear) in result, your template will not (again, "by default")
I saw wrong (totally wrong) result of templated output for the same range of status
good
>hg st --rev 1170:tip
M hggit\__init__.py
M hggit\compat.py
M hggit\git_handler.py
M hggit\gitdirstate.py
M hggit\hg2git.py
M tests\test-illegal-contents.t
my
>hg st --rev 1170:tip --template "{files % '{file}\n'}"
hggit/__init__.py
hggit/__init__.py
hggit/__init__.py
hggit/__init__.py
hggit/__init__.py
hggit/__init__.py
(six times files from tip only instead of range)
Even with hg log -T instead of st (which give all files) you'll have problem from p.1: "more than one file-entry in output for the same file"

How to get the list of all files in all branches?

Is there any way to get the list of all files (say all js or all css files) in my repo across ALL THE BRANCHES.
For example:
In my 'default' branch, i might not have a file named file1.js.
But in another branch named 'NEW_BRANCH', file1.js may exists.
I wanted to get the list of all files from one place or one command.
What about getting all files from all revisions including those still present, renamed and deleted?
hg manifest --all
If you only want files from the top of all branches (thus heads, then we iterate over all named and unnamed branches), you'll have to resort to some bash or similar, e.g.
for h in $(hg heads -T"{rev}\n"); do hg ma -r$h; done | sort | uniq
Some thing as?:
for b in `hg branches|cut -d ' ' -f 1` ; do echo "${b}: " ; hg manifest -r "branch(${b})"|grep ".css" ; echo

Retroactively use Mercurial rename

In my project, I haven't been using hg remove, hg mv or hg addremove due to ignorance. Consequently, every time I've renamed or moved a file, the history of that file has been messed up and now when I look at an individual file's history, I will only see a portion of the history.
What I'm looking for is a way to go back and retroactively fix all of those renaming mistakes so that the file history will stay together. What I imagine would be most likely is a way to edit the data in ".hg\store\data" to make this work. I've been experimenting, and I see the lines copy: and copyrev: in the data for the files I've renamed, so I suspect that has something to do with it.
Assume that I have control of the central repository and that there are no clones of it currently.
Summary:
Since you have full control of the repo this can be 100% fixed using normal hg commands.
The principle idea is to insert new changesets in the right places which effectively correct the original ones.
Let's say your history looks like this:
A-B-C-*
(* is your working folder)
and it was in B that you renamed a file in the filesystem without renaming it in hg.
Do this:
hg up A
hg revert -r B --all
hg mv oldfilename newfilename
hg commit -m <message>
The key here is using revert which is used to copy changes from a changeset into your working folder. This only works this way because you have updated to the predecessor of the changeset you are reverting.
at this point your history looks like:
A-B-C
\
B'-*
where B' is the "corrected" variant of B. Continue with:
hg rebase -s C -d B'
and you have:
A-B
\
B'-C-*
You can now clean up by doing:
hg strip B
leaving just:
A-B'-C-*
Of course where I used revisions like B you need to type the actual revision # or hash.
You could also use TortoiseHG or some other GUI to do a lot of these steps.
This answer covers the situation where you do NOT have full control of the repo. Its a little trickier and you can't get quite as clean of a result, but it still can be dealt with using normal hg commands.
The principle idea is to insert new changesets in the right places which effectively correct the original ones, and merge them after the fact.
Let's say your history looks like this:
A-B-C-*
(* is your working folder)
and it was in B that you renamed a file in the filesystem without renaming it in hg.
Do this:
hg up A
hg mv oldfilename newfilename
hg commit -m <message>
at this point your history looks like:
A-B-C
\
B'-*
where B' is the "corrected" variant of B. Continue with:
hg up C
hg merge B'
hg commit
and you have:
A-B-C-D-*
\ /
B'
If you look at the file history of the file in question, it will look something like this:
o D merge
|\
| o B' rename file
| |
o | B change where the file should have been renamed
|
o A some earlier change
/
o ...
|
o ...
So the history is all linked together for the file. Its just a little weird that B looks like it started from nowhere (because it actually did).

how do I open files with conflicts during git/mercurial merge in textmate/sublime

how do I open from terminal window only files with conflicts during git/mercurial merge in textmate/sublime text2 editors
You can use the following to open all files with git merge conflicts in sublime text:
git diff --name-only | uniq | xargs subl
I wanted to add another answer. git diff --name-only will give you all files that have diffs. This is why sometimes it will yield duplicate entries because it marks the file as "modified" as well as in a merge conflict state. Piping it into uniq is a good solution for this but git diff --name-only will also include files you might have purposely changed so it doesn't actually filter only files with merge conflicts. When you are in the middle of rebasing, this is probably not going to happen often though I would say in most cases #StephanRodemeier's answer works.
However, what you can do though is leverage the --diff-filter option which assigns a states to files. See more in the docs
--diff-filter=[(A|C|D|M|R|T|U|X|B)…​[*]]
Select only files that are Added (A), Copied (C), Deleted (D), Modified (M), Renamed (R), have their type (i.e. regular file, symlink, submodule, …​) changed (T), are Unmerged (U), are Unknown (X), or have had their pairing Broken (B). Any combination of the filter characters (including none) can be used. When * (All-or-none) is added to the combination, all paths are selected if there is any file that matches other criteria in the comparison; if there is no file that matches other criteria, nothing is selected.
It seems when files are in the both modified state, the diff status gets set to U (Unmerged) and M (Modified) so you can filter for only Unmerged files.
git diff --diff-filter=U --name-only | xargs subl
Should work without needing to pipe into uniq
Another thing you can consider is simply setting your editor as the difftool i.e. for VSCode documentation specifies how to do this by adding this to your .gitconfig
[diff]
tool = default-difftool
[difftool "default-difftool"]
cmd = code --wait --diff $LOCAL $REMOTE

How to get list of files that were affected since a specific revision in Mercurial

How do I get a list of all files affected in a changeset since rev 3456?
Note:
I tried hg log --rev 3456:tip --template "{files}"\n but there are several problems
If a changeset affects multiple files, they all appear on the same line.
This also shows the same file multiple times if a file was involved in many changsets.
hg stat --rev 3456
hg stat --rev 3456:tip to exclude uncommitted changes
There's a previous question that covers the same issue, with the added restriction that the search be restricted to files belonging to 'myself.' You can simply remove the '--user' and it should do what you need.
create a file named "mystyle"
changeset = "{files}"
file="{file}\n"
Then hg log --style mystyle --rev 3456:tip | sort | unique