Generate Hg diff (or patch) that Only includes content for files modified by a revision/revset - version-control

Given a large codebase and two revisions or revsets (say, a local 'source' and a target) which may or may not share a recent parent and usually contain a large number of non-relevant file deltas;
How can diff output be generated to compare the changes only for files that are modified in the source revset itself?
(This should be the delta between the ancestry; but only for the files contained within the revset.)
Using hg diff -r target -r source shows all the changes in the ancestry, even for files not modified by the source sevision.
In addition, this should be done without any knowledge of the directory structure.

If I understand correctly, you want a diff between revs source and target, but you want to restrict it to the files that were modified in changeset source. You can do it in two steps (easily assembled into one with an alias or shell script):
List the files modified in source:
hg log -r source --template '{files}'
This just outputs a list of filenames.
Request a diff for these files:
hg diff -r target -r source $(hg log -r source --template '{files}')
Step 2 is a bash command with "command substitution" $(...), which inserts the output of step one. Other methods are possible.

From hg help diff
If only one revision is specified then that revision is compared to the working directory
i.e. you can try hg up $SOURCE; hg diff -r $TARGET

Related

Perforce: How can I get files "as of" a date or revision from before a branch action?

Consider the following revisions of a file:
branch -1---2---
/
/
main 100--101-102--103---104---
I am currently in my branch and the file is synced to revision 2. I know that p4 has kept the history of the file, because I used merge and not copy, and indeed the history shows revisions previous to 103 (inclusive) when I look at the history of the file and check the option "Follow branch actions".
I would like to roll it back to revision 103 or before. Is this possible?
Answers for p4v preferred, but I'll take command line statements if that's the only way to do it.
The copy command is the best way of doing this:
p4 copy main#103 branch
Another option would be to use integ -f:
p4 integ -f main#103 branch
p4 resolve -at
One benefit of copy is that if you're doing this across a bunch of files (e.g. main/...#2018/01/01 to get all of main as of Jan 1) and some of them are already identical to the rev you're copying from because they haven't changed in that time, copy will leave them alone, which makes the result less noisy.

Find the list of file changes since last commit using mercurial

I am working on a project and I have to find the number of files added, deleted and modified since the last commit in mercurial hg.
hg status gives us the list of files which are modified, deleted and unknown. So using hg status is there any way i can get a count of all files added, deleted and modified?
Each file added, modified or deleted is listed on a line by itself, so you can count the lines for each. For instance, on Unix-like systems with the wc command:
hg status --modified | wc -l
Since the last commit it's always 0.
Describe your business-task in business-words

mercurial hg partial checkin

It is a very simple and stupid question,
I am working on 2 tasks and modified 2 sets of files in the code.
Now when I type 'hg ci', it checks in all the files. Can I remove certain files from the checkin i.e. do checking for only one task?
If I remove the files in the 'check in message' will they be removed from the checkin
Thanks for all the answers
This seems like a big flaw, My use case is very simple and general. Most of the time dev are working on various tasks , some are ready , some are not, bug fixes etc.
Now the only simple solution seems to be multiple local repos or clones
Use hg ci <files>... to commit only certain files in your working directory.
If you want to pick file by file you can use the record command. It ships with mercurial, but you have to turn it on if you want to use it by putting: record= in the [extensions] section of your ~/.hgrc.
It goes hunk by hunk, but you can answer for a whole file:
y - record this change
n - skip this change
s - skip remaining changes to this file
f - record remaining changes to this file
d - done, skip remaining changes and files
a - record all changes to all remaining files
q - quit, recording no changes
? - display help
I'll point out that if you're committing some files but not others it's certain that you've not run your test suite on the one change without the other, but maybe that doesn't apply in your case.
This isn't possible with mercurial out of the box. As have been suggested there are several ways of selecting what files you want to commit. To get this function via the commit message template, you would need an extension or a shell script wrapping the commit command. Here's one way to do that:
[alias]
ci = ! hg-partial-commit
hg-partial-commit:
#!/bin/sh
# partial commit
edit=$(mktemp ${TMPDIR:-/tmp}/$(basename $0).XXXXXXXXXXXX)
filelist=$(mktemp ${TMPDIR:-/tmp}/$(basename $0).XXXXXXXXXXXX)
logmessage=$(mktemp ${TMPDIR:-/tmp}/$(basename $0).XXXXXXXXXXXX)
cleanup="rm -f '$edit' '$filelist' '$logmessage'"
trap "$cleanup" 0 1 2 3 15
(
echo user: $(hg debugconfig ui.username)
echo branch: $(hg branch)
hg parents --template 'parent: {rev}:{node|short} {author} {date|isodate}\n'
echo
echo 'Enter commit message. Select files to commit by deleting lines:'
hg status 'set:not unknown()' | sed -e 's/^/#/'
) | sed -e 's/^/HG: /' >"$edit"
${VISUAL:-${EDITOR:-vi}} "$edit"
egrep -v '^HG:' "$edit" >"$logmessage"
egrep '^HG: #' "$edit" | cut -c8- >"$filelist"
hg commit -l "$logmessage" "listfile:$filelist"
$cleanup
The real problem here is the fact that you're doing changes related to different tasks jumbled together. Mercurial has a few ways you can keep things separate.
Task Branches
Suppose you've been working on a task and you've checked in a few times since you last pulled, but things aren't ready to share yet.
o----o----B----o----o----o
Here, B is the revision where you started your changes. What we do is (after making sure our current changes are checked in):
> hg update -r B
<do our work on the other task>
> hg commit
We've now created a new branch with the changes for this task separated from the changes for our original task.
o----o----B----o----o----o
\
----o
We can do this for as many different tasks as we want. The only problem is that sometimes remembering which branch is which can be awkward. This is where features like bookmarks come in useful. A bookmark is a tag which moves forward as commits are made so that it always points at the head of a branch.
Mercurial Queues
MQ adds the ability to work on changes incrementally and move between them by pushing and poping then off a stack (or "Queue" I guess). So if I had a set of uncommitted changes that I needed to split up I'd:
> hg qrecord taska
> hg qrecord taskb
> hg qrecord taskc
I'd use the record extension (or more likely the crecord extension) to select which parts of files I want to select.
If I needed to go back to taska and make some changes:
> hg qpop; hg qpop # pop two off the queue to go back to task a
<Do changes>
> hg qrefresh # update task a with the new changes
When I want to turn the queue into normal changesets:
> hg qpush or hg qpop # get the changes I want converted onto the queue
> hg qfinish -a # converts mq changes to normal changesets
There's other methods too, but that will do for now.
You will unavoidably have to either specify the files that you want to add or the files you want to leave out. If you have a lot of files, as you indicate above, the following steps will simplify the procedure (I'm assuming a UNIX-ish system here, Windows would be slightly different).
First, generate a list of changed files:
hg status -mard -n >/tmp/changedlist.txt
The -mard options will list all files that were modified, added, removed, or delated. The -n option will list them without the status prefix so that all you have is a raw list of files.
Second, edit /tmp/changedlist.txt with your favorite text editor so that it contains only the files you wish to commit.
Third, commit these files:
hg commit `cat /tmp/changedlist.txt`
You will be able to review the files to be committed before actually performing the commit.
Alternatively, you can add more files to a commit incrementally by using
`hg commit --amend file...`
Here, hg commit --amend will not create a new commit, but add the new files to the existing commit. So, you start out with committing just a couple of files, then incrementally adding more until you are done. This still requires you to type all of them in.
For yet another alternative, you can use Mercurial Queues to split a commit in more sophisticated ways, but that's a bit more of an advanced topic.

How can I list all files I created?

I would like to get a list of all files in the current revision that were initially created by me. Does anyone know how I can do this?
Here's another approach that's a bit more direct.
for f in `hg locate`; do hg log -r "first(follow('$f'))" --template "$f: {author}\n"; done
Translation:
for each file
follow its history to the beginning
print the filename and author
To simply get a list of files first introduced by Bob:
for f in `hg locate`; do hg log -r "first(follow('$f')) and author(bob)" --template "$f\n"; done
Here's how you could do it on unix or mac:
for therev in $(hg log --template '{rev}\n' --rev 'author("ry4an")') ; do
hg status --added --no-status --change $therev
done
I'm afraid I've no idea how you'd do it on developer-unfriendly OSes. That gets all files you ever added, so you'd need to compare with hg manifest if you wanted to remove files that aren't in the current tip revision.

command line recursive word-based diff?

is there a command line program that gives recursive word-based diff (on 2 directories)?
diff -u is recursive, but it doesn't do word by word comparison. wdiff and dwdiff does word based diff but there are not built-in options for recursive diff.
I would like to pipe the result to colordiff so a program that generates output that colordiff understands would be especially useful. Any suggestions? Thanks!
CC
Git can do it and output color:
The following often works:
git diff --color-words path1 path2
but in general you may need to do
git diff --no-index --color-words path1 path2
Neither file even needs to be in a git repository!
--no-index is needed if you and the paths are in a git working tree. It can be elided if you or one of the files are outside a git working tree.
Manpage: https://git-scm.com/docs/git-diff/1.8.5 (and later...)
git diff --no-index [--options] [--] […​]
This form is to compare the given two paths on the filesystem. You can
omit the --no-index option when running the command in a working tree
controlled by Git and at least one of the paths points outside the
working tree, or when running the command outside a working tree
controlled by Git.