If I mark a "missing" file (indicated by a !) for remove, (for example this can be done by accidentally finding the wrong rename), how do I unmark it, and get it to be "missing" again? I find that the file becomes stuck at R state, and then hg rename will give a message like not copying - file has been marked for remove. There are various commands like remove which will mark a file to take some action on the next commit, but is there a way to clear this flag and return the file back to the unmarked state?
Usually if you have sth. like this
! foo.txt
One possible solution:
hg revert foo.txt
Or you can update only the file to latest revision without a conflict like
hg update -r <rev-id> foo.txt
Usually
hg log
should give enough information to perform this step
If you want any further help, please post output of
hg status && hg log
Related
I'm trying to write a small script for my team that automatically updates the feature branche to a case and then creates a branch for review. I've got the commands down manually but I'm having trouble making it a bit more hands off.
For now, I want to use this templated command:
hg log --rev <changeset> --template "{branch}\n"
Which returns the branch name of a changset. Then I would like to remove a portion of the name and prepend a string. For example, a branch would be named case-1234-FeatureDescription and I would want to be creating a branch named review-1234-FeatureDescription
Ideally, I would like to pipe the output of this command to the branch command
hg branch <result-of-previous-command>
Is it possible to do this?
You suggest to create a branch by a name which you just extraced from the logs of the very same repo. That doesn't exactly look like it can succeed as it already exists.
Additionally, it likely is probably not a good idea to create a named branch for each review process as branch names are persistent. You might consider to use bookmarks for that purpose as they can be deleted without trace from the repo after review is completed.
I'd suggest to use - without piping - something like
hg bookmark -r CHANGESET $(hg log --rev CHANGESET -T"{branch}")-review
i looking to get the files which are tagged with a specific changeset.
I would like to copy it to another directory, how can i do it ?
Thankss
The question isn't clear, but if you want a complete set of files from a specific tag just do:
hg archive -r <tag> <destinationdir>
See hg help archive for details.
hg st --change [rev] will show a list of the files that changed in a given revision. Since mercurial recognizes a tag name for a revision automatically (assuming it's unique to the revision hashes) this will work with a tag name as well.
If you want to copy these files in an automated fashion, you'll need a clean list; also, you probably just want the files that are there, not the ones removed/deleted. For this you'd use
hg st -man --change [rev]
Using this list to copy these off somewhere else will be platform/shell dependent. From Windows commandline, at the root of your repo, you could do something like
for /f %I in ('hg st -man --change [rev]') do copy ..\changes
, although that won't preserve subdirectory paths. I'll leave that as an exercise for the reader :)
UPDATE
Sorry, I should also have noted that you'll need to update to the revision in question if you want to copy the files as they were at the time of said revision (I'm assuming here, but this seems like the natural reason to want to do this...).
I have a repos which I'm about to split in two (using hg convert). I'd like to take the opportunity to get rid of (exclude) unnecessary directories. However, in some cases, I moved files around using hg cp and so forth, so seemingly unused directories may have old history assocated with them, and in some cases I have verified they do. (In most cases this is very old history (from around 2004/2005). I do this much less now). Is there a way I can check a particular directory does not share history with the current tip? By this I mean that for a directory foo:
hg log -vf filename
for all filename in tip does not mention any files in foo.
I think that is a sufficient criteria.
EDIT: I belatedly realized that the above question is wrong. In my case most of these original directories are still in tip, so what I said above won't work. Instead, say DIR_1, DIR_2, ..., DIR_k is directories which are currently (in tip) no longer relevant. I want to make sure they never were relevant. In other words, consider all files not in any of DIR_1, DIR_2, ..., DIR_k. Then check that their ancestors doesn't include a changeset in any of these DIR. If it does, then I guess you need to exclude that directory from the list of non-relevant directories, and try again.
EDIT2: Ok, let's break this down a bit. Can someone tell me what the expression for the set of all csets which touch files in a specific directory DIR is? The following seems close, but I'm not sure how to interpret the expression **.*.
hg log -vr "file('c++/**.*')"
Try for directory DIR such revset
hg log -r "ancestors(tip) and file('DIR/**.*')"
Any output means "Found in history"
I finally settled on the following script.
Brief description: The basic idea is to find directories which aren't part of the history of the files in the tip. So, this script takes all files in the tip and removes those from the chosen set of directories. Then it does hg log -vf for each of those files, and checks whether any of the files in that log match the files in that set of directories. If they don't, then those directories can be safely deleted.
I am sure this script could be improved - my shell scripting is quite dodgy. Suggestions for improvement appreciated.
#!/bin/sh
hg locate "set:not lisp/** and not boost/** and not trunk/** and not 'c_api_ex/**' and not 'c++-strategy/**' and not parallel/** and not poster/** and not sim/**" > file.txt
while read f; do
filelist=$(hg log -vf $f --template "{files % ' {file}\n'}")
one_file_per_line=""
for file in $filelist
do
one_file_per_line="${one_file_per_line}""\n""${file}"
done
filematches=$(echo -e $one_file_per_line | sort -u | egrep 'lisp/|boost/|trunk/|c_api_ex/|c++-strategy/|parallel/|poster/|sim/')
if [ -n "${filematches}" ]; then
echo file $f has the following files as ancestors in one or more of lisp, boost, trunk, c_api_ex, c++-strategy, parallel, poster, sim directories: $filematches
fi
done < file.txt
What mercurial command can you use to see the changeset prior to changeset xyz?
If you do hg log -r :xyz you see all the changesets prior to (and including) xyz - listed in ascending order. But I'd like to easily see just the prior changeset.
Update: Really what I'm after is this: If I do an hg fetch, what command can I use to see the changeset PRIOR to the the changesets that were pulled in by the fetch?
hg log -r :xyz where xyz is the first changeset pulled in by the fetch works but it returns the entire list of prior changesets where I just want the most recent.
You can't do it. Once you've pulled (and fetch is just pull + either update or merge) there is no record of what you had before the pull and what you just got from the pull.
You should do hg incoming before you pull to see what you will get.
Also, stop using fetch. The acts of pulling and updating and merging are completely separate and doing them in a single commands provides inadequate error reporting and just confuses things. The command is disabled by default and there's talk of removing it entirely. Merging is coding, and it shouldn't be hidden.
Expanding to Show cases you can't cover
If before fetching your history is this:
[A]-[B]-[C]
and you (against all advice) fetch and get [D] you now have:
[A]-[B]-[C]-[D]
And you can see exactly what's new with:
hg diff -r tip-1
or with:
hg diff -r "parent(tip)"
But if starting again with A,B,C you fetch and get D,E yielding this:
[A]-[B]-[C]-[D]-[E]
there is no command you can run to see "what changed" without having previously written [C] down on a post it note.
If, on the other hand your repo started out looking like this:
[A]-[B]
\
-[C]
and after fetching you have this:
[A]-[B]-[D]
\
-[C]-[E]
there's no single command that will tell you "what changed". Similarly, if before pulling your repo looked like this:
[A]-[B]-[C]
and after fetching you got this:
[A]-[B]-[C]-[E]-[F]
\ /
-[D]-------/
where [F] is the new ill-advised auto-merge changeset fetch created then the command:
hg diff -r C
will tell you what's new, but there's no way to look up 'C' without having previously written it down.
I assume xyz is a changeset in hash form. Try:
hg log -r :xyz-1
That should work to list just the changeset prior to 1
I'm not sure what is meant by prior. Your question could mean you might just want the parents of the changeset. These you would get easily with
hg parent -r xyz
This does not need fancy new versions of mercurial.
hg parents [-r REV] [FILE]
show the parents of the working directory or revision
Print the working directory's parent revisions. If a revision is given via
-r/--rev, the parent of that revision will be printed. If a file argument
is given, the revision in which the file was last changed (before the
working directory revision or the argument to --rev if given) is printed.
options:
-r --rev show parents of the specified revision
--style display using template map file
--template display with template
--mq operate on patch repository
With the parentrevspec[1] extension installed, you can use the git-like syntax below. Depending on your shell, the quotes may not be necessary.
hg log -r 'xyz^'
https://www.mercurial-scm.org/wiki/ParentrevspecExtension
As the definite guide aptly points out (search for "Tags and cloning"):
When you run hg clone -r foo to clone a repository as of tag foo, the new
clone will not contain any revision newer than the one the tag refers to,
including the revision where the tag was created. The result is that you'll
get exactly the right subset of the project's history in the new
repository, but not the tag you might have expected.
It means hg tags in your new clone does NOT show the foo tag. Same thing happens if you had cloned before foo tag was added, and you do hg pull -r foo.
(Digression: tag is about the only thing I don't quite get in hg. I understand there are advantages (e.g. merge) in putting it in a changeset, but it always feels weird to have meta data mixed with source code.)
It should be obvious that I'm asking for an automated way, instead of pulling the tag changeset as a separate manual step.
I know I could check for this scenario in an incoming hook (so it works for both clone and pull), or wrap clone and pull.
But is there a better/easier way?
UPDATE hg bug tracker already has this issue.
You want a giant hack with bash and an embedded Perl script? Well, here it is...
#!/bin/bash
if [[ "$1" == "" || "$2" == "" || "$3" == "" ]]; then
echo 'hgclonetag <src> <tgt> <tag>'
exit 1;
fi
REV=`hg log -R $1 --rev $3: --limit=2 | perl -F: -lane 'if (/:([\dA-Fa-f]+)$/) {print $F[2] if defined($flag);$flag=1;}'`
hg clone --rev $REV $1 $2
This invokes the hg log command to extract the revision number after the first tag-related revision and then clones to this revision.
Currently this does not work on remote repos: -R switch only works on local repos unfortunately.
The more I think about it the more I'm convinced the right answer is to just clone everything and update to the tag, which can be done in a single step:
hg clone http://host/path#tagname
That gets you everything and then does hg update to tagname which sets your working directory to the correct revision. Given delta compression that's not necessarily much larger, and if it is you can automate cloning the bulk of it from a previous local clone.
There is a postclone hook. It's called post-clone (the hgrc manpage shows a post-ANYCOMMAND and pre-ANYCOMMAND exist) though as you pointed out you could also use *changegroup or update hooks too, since clone uses both of those functions (unless you suppress update with -U).
What about just adding a --localtag so you have the name but not the extra changeset if you need it for reference only. Something like
hg clone -r tagname URL
hg tag --local tagname
which you could easily build into a shell alias.
Other than that there's not necessarily guaranteed to be a way to have revision X and the revision where revision X is tagged without also having other revisions you don't want since the tag could have been applied after other work was done. You can, of course, always update to 'X' and to have subsequent changesets in you working dir, but they'll still be in your repo.
Honestly, once I figured out that the tag name doesn't come a long when you clone up to a tag, which I admit confused the heck out of me at first, I didn't find any need to bring along the changeset with the tag in it.
Yes it can be done by post-clone/pull hooks, but there are a couple of crooks.
First, it only works for local repo, since you can't get the list of tags in a remote repo.
Second, dealing with clone/pull arguments and options is not trivial. (For clone I need to get the target repo, -r, -u, -U. For pull I need -r and -u.) I tried to use fancyopts, but it can't deal with global options, which are processed away in dispatch. I managed to hack dispatch to give me only the args and opts of a command, but it feels and looks ugly.
Using command wrapper would eliminate the second problem.
I hope one day hg will add an option to clone and pull to do it cleanly.