Delete local bookmarks that haven't been touched in 7 days - mercurial

How should I clean up all the local bookmarks that hasn't been touched recently (say in the past 7 days)? Using
hg bookmark -d <bookmark name>
seems unscalable.

To my knowledge there is no information as to when a bookmark was updated to last or when it was created; you can only obtain the information of the age of the commits they are attached to easily, e.g.
hg log -r "bookmark() and date('-1000')"
hg log -r "bookmark() and date('<01/30/2015')"
for all bookmarks attached to commits created in the last 1000 days or all bookmarks attached to commits older than January 30th 2015.
EDIT to add: There is the Journal Extension. It allows to actually track when and to which revisions a bookmark was attached to. Thus you might want to enable this extension if you want to solve your problem for the future.

hg bookmark -d can take multiple arguments, so combining with the answer above you can do:
hg bookmark -d `hg log -r "bookmark() and date('-1000')" -T '{bookmarks} '`
I use this to remove all public bookmarks, since I only use them locally:
hg bookmark -d `hg log -r "bookmark() and public()" -T '{bookmarks} '`

Related

How to prune bookmarks for/after hg pull?

Is there an option for hg pull to force-update (non-forward) all bookmarks or even prune all bookmarks which are not present in the remote repository anymore?
By "pruning" I mean to get rid of local bookmarks which are not present in the remote repository anymore. Otherwise, local bookmarks would constantly accumulate even they are already obsolete.
Put it with other words, I would like to work with bookmarks as I would work with Git (remote) refs.
If there is no built-in way to do this, what is the recommended sequence of commands to perform these tasks?
The question is not entirely clear, so I'm taking a bit of a guess here. Bookmarks will normally be updated during a pull, unless they were changed to point to an earlier revision. In this case, you can use hg pull -B <bookmarkname> to pull a bookmark, anyway.
If by pruning bookmarks you mean deleting them from the remote server, you first have to delete them locally, then push the deleted bookmark. I.e.
hg bookmark -d <bookmarkname>
hg push -B <bookmarkname> <repository>
The easiest way to get rid of all bookmarks that don't exist on the remote repository is to first delete all inactive ones, and then pull from the repository again.
Example:
hg bookmark -d $(hg bookmarks | awk '{if (NF == 2) print $1;}')
hg pull
You can put the first command in your .hgrc file as an alias, e.g.:
[alias]
clrbookmarks = !$HG bookmark -d $($HG bookmarks | awk '{if (NF == 2) print $$1;}')

Discard all and get clean copy of latest revision?

I'm moving a build process to use mercurial and want to get the working directory back to the state of the tip revision. Earlier runs of the build process will have modified some files and added some files that I don't want to commit, so I have local changes and files that aren't added to the repository.
What's the easiest way to discard all that and get a clean working directory that has the latest revision?
Currently I'm doing this:
hg revert --all
<build command here to delete the contents of the working directory, except the .hg folder.>
hg pull
hg update -r MY_BRANCH
but it seems like there should be a simpler way.
I want to do the equivalent of deleting the repo, doing a fresh clone, and an update. But the repo is too big for that to be fast enough.
Those steps should be able to be shortened down to:
hg pull
hg update -r MY_BRANCH -C
The -C flag tells the update command to discard all local changes before updating.
However, this might still leave untracked files in your repository. It sounds like you want to get rid of those as well, so I would use the purge extension for that:
hg pull
hg update -r MY_BRANCH -C
hg purge
In any case, there is no single one command you can ask Mercurial to perform that will do everything you want here, except if you change the process to that "full clone" method that you say you can't do.
hg up -C
This will remove all the changes and update to the latest head in the current branch.
And you can turn on purge extension to be able to remove all unversioned files too.
To delete untracked on *nix without the purge extension you can use
hg pull
hg update -r MY_BRANCH -C
hg status -un|xargs rm
Which is using
update -r --rev REV revision
update -C --clean discard uncommitted changes (no backup)
status -u --unknown show only unknown (not tracked) files
status -n --no-status hide status prefix
hg status will show you all the new files, and then you can just rm them.
Normally I want to get rid of ignored and unversioned files, so:
hg status -iu # to show
hg status -iun0 | xargs -r0 rm # to destroy
And then follow that with:
hg update -C -r xxxxx
which puts all the versioned files in the right state for revision xxxx
To follow the Stack Overflow tradition of telling you that you don't want to do this, I often find that this "Nuclear Option" has destroyed stuff I care about.
The right way to do it is to have a 'make clean' option in your build process, and maybe a 'make reallyclean' and 'make distclean' too.
If you're looking for a method that's easy, then you might want to try this.
I for myself can hardly remember commandlines for all of my tools, so I tend to do it using the UI:
1. First, select "commit"
2. Then, display ignored files. If you have uncommitted changes, hide them.
3. Now, select all of them and click "Delete Unversioned".
Done. It's a procedure that is far easier to remember than commandline stuff.

How can I see a list of all files that are different between two Hg repositories?

I've got a repository that has a lot of working code. Another developer on my team went without any updates for a while and then committed about 5 changesets. So, now we have two heads that are nearly two weeks apart. The tip doesn't work, but my changeset does.
I want to see what the differences are between the two repositories without having to merge them (because I'm not sure I want to do that).
Andrew's answer tells you how to see the differences between the files. This is great when you need all the details. But here is how to directly see the names of the files themselves:
hg status --rev X --rev Y
As you all know, the status command is normally used to see what has changed in the working copy since the last commit, or more accurately, since the working copy's parent revision (see hg parents or look it up in hg glossary if you don't know what that is). However, the status command can also be used to compare other revisions.
This can be used for all sorts of nice things... an example would be for writing release notes where it would be nice to mention any new translations introduced since the last release. For Mercurial itself, I can do:
% hg status --rev 1.6.2 --rev tip i18n
M i18n/da.po
M i18n/it.po
M i18n/pt_BR.po
A i18n/ro.po
to see that the Romanian translation is new and that the Danish, Italian, and Brazilian Portuguese translations have been updated. In this case, my working copy parent revision was the tip, so I could have left out --rev tip.
If you have both heads in your repository (remember, you don't actually have to update your working copy with the other developer's head), from the root directory of your working copy:
hg diff -r <your head changeset id> -r <other dev changeset id> .
should work. Of course, you can use hg heads to get the changeset ids, one of which it sounds like could be "tip".
If the above returns too much information, and you just wish to know what files changed, try piping through grep:
hg diff -r <your head id> -r <other dev id> | grep -E '^\+{3} b/'
will probably do the trick.

Using Mercurial, how to diff with a fixed revision if commit intermediate states often?

Using Mercurial, say if I do an hg pull and hg up and now the local repo and working directory are both up to date.
What if I commit often, say 1 day later, and then 2 days later, and want to diff with the revision as of right now?
Otherwise, the diff is always comparing to the previous committed version.
I can use pencil and paper and write down the revision number right now, say, 4117, and then 1 day later, 2 days later, and any time before I am sure and push to the remote central repo, do an
hg vdiff -r 4117
(either using vdiff or diff). But instead of remembering this "magic number" 4117, is there a way to make Mercurial somehow remember this number? That way, hg vdiff is to see the difference between minor changes against committed code, but there is a diff that shows all changes before pushing to the remote repo.
(or, if there is command that shows the revision number since your last pull, which should also show 4117, so on bash we can do something like hg vdiff -r `hg --what-is-last-pull` )
Update: does hg out --patch show the diff of what would be pushed to the remote repo? If so, maybe it serves the purpose without caring the "magic number". But how to show the patch diff using kdiff3 or any other diff tools? Also, it seems we can do hg out and if we see 4118, 4119, 4120, then we know if we do hg vdiff -r ___ we should use (4118 - 1) which is 4117.
Update 2: actually, hg out --patch shows the diff between local repo and the remote repo, so it is close, but not exactly the same as the diff between working directory and the local or remote repo.
If you want to mark a revision you can use bookmarks extensions. It is shipped with mercurial. Documentationis available here
In your case,
hg pull -u
hg bookmarks lastpull
..hack..hack..
hg ci -m new-hack
hg diff -r lastpull:tip
hg bookmarks -d lastpull
Do it with multiple clones. When you clone from the remote repo initially use clone -U to create a clone that has no working directory files at all. Then clone again locally, for example:
$ hg clone my-local-clone-with-no-working-files my-working-clone
Do your commits and work in my-working-clone and then at any time you can check the tip in my-local-clone-with-no-working-files to see what the last thing you pulled from the server was. If you want to get fancy you could create a shell alias for:
hg diff -r $(hg -R $(hg root)/../my-local-clone-with-no-working-files id -i -r tip)
which will compare the working directory of the repo in which you run it (my-working-clone) with the tip of whatever you last pulled from the server.
It's worth nothing that this takes no extra disk space because local clones use hardlinks under the covers the the my-local-clone-with-no-working-files has no working directory files.
You can replace pen and paper with a local tag: hg tag -l -r <revision number on paper> tagname. Notice the -l, which makes the tag local, which means it does not get transferred by push and pull. You can also remove this tag by hg tag -l --remove tagname.

In Mercurial (hg), how do you see a list of files that will be pushed if an "hg push" is issued?

We can see all the changesets and the files involved using
hg outgoing -v
but the filenames are all scattered in the list of changesets.
Is there a way to just see a list of all the files that will go out if hg push is issued?
First, create a file with this content:
changeset = "{files}"
file = "{file}\n"
Let's say you call it out-style.txt and put it in your home directory. Then you can give this command:
hg -q outgoing --style ~/out-style.txt | sort -u
A somewhat under-appreciated feature: hg status can show information about changes in file status between arbitrary changesets. This can be used to get a list of files changed between revisions X and Y:
hg status --rev X:Y
In this case, we can use hg outgoing, to find the first outgoing changeset X and then do
hg status --rev X:
to see the files changes since revision X. You can combine this into a single line in your shell:
hg status --rev $(hg outgoing -q --template '{node}' -l 1):
I usually use
hg outgoing -v | grep files
It makes the listing shorter, but doesnt sort. But thus far I havent been in a situation where I want to push so much (and at the same time check the files) that its been a problem.
[Edit]
To do what you want:
Use cut to remove the files: part
For changesets with more than one touched file, use tr to put them on separate lines
Finally sort the resulting output with sort
Like so:
hg outgoing -v |grep files: |cut -c 14- |tr ' ' '\n' |sort -u
You can put this in ~/outgoingfiles.sh or something to have it nice and ready.
I use Torgoise Hg, which is a shell extension that has a "synchronize" view allowing you to see outgoing files before you push them. It's convenient for commits as well, and other things.
A simple hg out will also solve this.
It will list all committed but yet to push checkins.