If "Adam" commits his changes locally on february 28, and doesn't push his changes to the "Main repo" until march 12th, the timestamp on his changeset still says "february 28". How do I find out what date the changes were pushed to the "Main repo"?
I don't believe Mercurial itself tracks this automatically. Instead, you have to set a hook for it on the central repository. The most obvious hooks are the "incoming" hook and the "changegroup" hook. You would set a hook like so:
(add these lines to the central repo's .hg/hgrc file, creating it if necessary)
[hooks]
changegroup.log = printf '%s\n%s' $(date -R) $(hg log "$HG_NODE::") >>/path/to/logfile.log
Anything pushed to that repository afterwards would be logged in /path/to/logfile.log, which you can parse or read manually. I'm not certain whether the log file needs to be world-writable for this to work; it would likely depend on your repository setup.
Mercurial doesn't record that information.
A pushlog is required to record the time of pushing to a server. See this similar question and its links which explains them.
Related
This is an extension of the following question:
Mercurial show number of commits ahead of "origin"
I want to find out the number of commits yet to be pushed to the remote repository without contacting the remote (So that I can add it to my prompt).
In git I can do that with:
git rev-list branchname#{upstream}..HEAD | wc -l //I am counting the number of lines to get the number of commits by which i am ahead.
The original answer advices to use:
hg summary --remote
But this contacts the remote repository and takes quite sometime, so putting it in prompt seems a bad idea.
Does anyone know if mercurial allows to do this, since the original question is quite outdated, i thought some new method or extension might have come up.
hg outgoing : log of everything that has yet to be pushed (but it does contact the remote repository)
hg log -r "draft()" : log all of the commits that are in draft phase in your repository (without contacting remote). This doesn't definitively mean that they are not in the remote repo, but it's very close.
You can use --template templates to customize the output.
Hope this helps.
Is there a way to edit a commit message in Mercurial on a commit after other commits have occured using TortoiseHg? I've read these posts:
How to edit incorrect commit message in Mercurial?
Mercurial: how to amend the last commit?
and have been able to update a "regular" commit message when it is the latest commit on a branch (using TortoiseHg). However, I haven't been able to figure out how to edit a commit message when other commits have occurred after the one I want to edit. It always edits the last commit.
Based on Ed Cottrell's comment, I did a test where I made two commits without pushing to the central repo, and I still have the same issue - only the last commit message can be edited.
EDIT: I should clarify that I am looking to update a changeset that has been pushed.
Histedit extension (bundled with TortoiseHG now) has a mess command for changing the commit message of historical changesets.
Unfortunately, this command is not supported by the TortoiseHG GUI so you need to run the command from command line.
As long as the change in question is local and hasn't been pushed anywhere, it is possible.
The commit message is used to compute the globally unique hash id that is used for all repositories to determine whether or not they already have a changeset. If you change the commit message, you change the unique hash id and every repo will see it as a "new" changeset. All other repositories that had the old changeset will try to get the new one and ask that you merge it with itself.... This is not a good thing, so the short answer to your question is "don't do it".
If you could definitively purge that change from all other repos, so that only the local copy is left you could essentially get to the "draft" state. Note that if any repo has the "old" changeset, it will be pushed to the central repo someday and cause the mess that we are trying to avoid.
If the changeset is still local (e.g. in draft status), you can use hg commit --amend if it is the parent of the working directory.
If there are changes after it, I would use mq and hg qimport all the changes down to and including the one where you want to edit the commit message. hg qpop -a and then hg qpush to get to the patch that represents the changeset you want to edit. Then hg qrefresh -e and make your changes. Then just hg qfin -a and you should be good to go.
The advice from Edward is good — if you've pushed your changes to another repository, you should consider them set in stone and not update the commit message or any other aspect of them.
However, we're working on changing this in Mercurial. There is an experimental extension that will allow you to do more extensive history editing and push those edits to other repositories. It is called the Evolve Extension and it enables some behavior that is partly in the core of Mercurial and partly outside core.
When using evolve, you can edit the second-to-last commit message like this
$ hg update .^
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
$ hg commit --amend -m 'new commit message'
1 new unstable changesets
$ hg stabilize
more:[5] old tip changeset
atop:[6] new commit message
The extension allows you to do this as long as the changesets are in the draft phase. To keep them in the draft phase after pushing them somewhere, the repository you push to need to be configured as a non-publishing repository. You can read more about this in the Changeset Evolution Documentation.
Is it possible to know when a certain commit was pulled from a distant repository and the files updated with Mercurial ?
More precisely, I made a hg pull -u a few days ago, and now I'd like to know if this pull downloaded only the last commit, or if there were some commits that had not been pulled yet, making my last pull getting them as well.
hg log seems to give the dates of the commits, but nothing about the updates. Is this information anywhere ?
This information is not recorded by Mercurial. A Mercurial repository is just a container for changesets and Mercurial does not store how (or when) the changesets entered the repository.
You can setup hooks for this, though you would have to build the scripts yourself. A very rudimentary system would be
[hooks]
pre-pull = (date; hg root; hg tip) >> ~/.pull-log
post-pull = hg tip >> ~/.pull-log
This would record the current date, the current repository, and the current tip in ~/.pull-log just before every hg pull. After the pull the new tip is recorded. You could build scripts that parse the log file to extract information about what each pull did.
hg log seems to give the dates of the commits, but nothing about the updates
Yes, hg log is only concerned with the stored history (changesets) and working copy operations like updating is not part of recorded history.
Finally, let me mention that this is the first time I've seen someone ask for a "pull log". However, the opposite is quite common: there are scripts for maintaining a "push log" on a server to see who pushed what and when. This is done by Mozilla among others. See this README for some starting instructions.
If you want to log when and with which revision hg update was used to update the code, then use these hooks:
[hooks]
pre-update = (echo "---------------------------------"; date --rfc-3339=s; hg root; echo "pre-update:"; hg identify --id --branch) >> .hgupdates
post-update = (echo "post-update:"; hg identify --id --branch) >> .hgupdates
the above hooks produce a log entry like this for each time hg update is run:
2015-12-23 00:44:31+02:00
/var/www/my/project
pre-update:
802120d1d3a0 somebranch
post-update:
302720d1d3d2 otherbranch
This also works when hg update is run without a specific revision flag (-r) set
I use named branches in Mercurial.
In doing so I have created one branch called playground where I can try out various wacky experiments. I never intend to merge this branch into any others and I never want to push it to our main repository.
Since creating it, every time I do a push I am told I have added a new branch and I have to use the --new-branch flag. At this point hg push -b default (or whatever branch I'm pushing) works fine but it's annoying. Is there any way to suppress that message by letting Hg know that I am not interested in pushing that branch ever?
Starting with Mercurial 2.1 (released in February 2012), you can mark your changesets secret to keep them from being pushed to another repository. You use the new hg phase command to do this:
$ hg phase --force --secret .
This mark the current working directory parent revision (.) as being in the secret phase. Secret changesets are local to your repository: they wont be pushed or pulled. Pushing now looks like this:
$ hg push
pushing to /home/mg/tmp/repo
searching for changes
no changes to push but 2 secret changesets
There is no equivalent mechanism in older versions of Mercurial. There your best bet is to create a local clone for the changesets you don't want to push.
Update:
Mercurial 2.1 introduced the hg phase command which allows users to control what change sets are exchanged with remote repositories. #MartinGeisler answer to this question details this method.
Original Answer:
If you want to create a local branch of your code you have a couple options. You can hg clone the repository which will locally create a branch of the entire repository in your filesystem. The other alternative is you can try to use a Mercurial extension like LocalbranchExtension.
There are many ways to branch in Mercurial without using a named branch. Just find a method that suits your needs.
Further reading: http://stevelosh.com/blog/2009/08/a-guide-to-branching-in-mercurial/
In addition to the excellent answer above concerning phases, you can also specify 'default-path' (in the [paths] section of your .hgrc) to refer to the local repository:
[paths]
default = ...
default-push = .
This will cause all outgoing changesets to be compared to the specified repository. In this case, comparing outgoing changesets in your local repository TO your local repository results in nothing to push.
You can still pull/update/merge from the main repository, but no push will ever send anything back to that main repository.
If you work on multiple machines/repositories, you can set one up as described above, and configure the others to specify the 'default' path to point to the server that pushes to itself. In this way, the other machines can push/pull to your local central repository, and these changesets will never escape your carefully configured collection of repositories.
After a change in my local repo, I commit with hg commit -m <message>, then I push to my server with hg push, then in my server I update working dir with hg update.
Is there a better way to do this?
The first two steps you have described:
hg commit -m <message>
hg push
are required as per the fact that commits are kept completely separate from the server in Mercurial (and most other DVCS as well). You could write a post-commit hook to perform the push after each commit, but this is not advised because it prevents you from correcting simple mistakes during the commit and before the push.
Because you're trying to perform an update on 'the server' I'm assuming you are executing a version of the code in your repository on the server. I'm assuming this because typically the server would simply act as a master repository for you and your developers to access (and also to be subject to backups, etc..), and would not need the explicit hg update.
Assuming you are executing code on the server, you can try and replace the push and the update with this command:
hg pull <path to development repo> -u
which will perform a pull from your local repo and then an automatic update. Depending on your server configuration, it might be difficult to get the path to your local repo.
For the first part of the question (ie. automatically push when you do a commit), you can use the trick described in this answer : mercurial automatic push on every commit .
If you want to automatically update the working directory, you can do this with a hook. Add this in the hgrc of your repository (.hg/hgrc on your server directory) :
[hooks]
changegroup = hg update >&2
This will automatically update the working directory every time a push is made to this server. This hook is described in the Mercurial FAQ.
If you use these 2 solutions, the next time you do hg commit -m "message", the commit will be automatically pushed to the remote server and the working directory on the server will be updated.
There is an extension called autosync you might find useful:
This extension provides the autosync command which automatically and continuously commits working copy changes, fetches (pull, merge, commit) changes from another repository and pushes local changes back to the other repository. Think of configuration files or to-do lists as examples for things to synchronize. On a higher level the autosync command not only synchronizes repositories but working copies. A central repository (usually without a working copy) must be used as synchronization hub: