Example scenario:
revision #100 - user1 makes a commit on DEV branch in 2017-01-01
revision #101 - user2 cherry picked user1's commit to master branch (hg graft -r 100) in 2017-01-02
hg log:
changeset:101
user: user1
date: 2017-01-01
summary: message 100
changeset:100
user: user1
date: 2017-01-01
summary: message 100
But how would I know user2 pushed revision #101?
You cannot (besides what Lasse suggest in his comment).
Consider:
touch a; hg add a; hg commit -m 'Add a as myself'
touch b; hg add b; hg commit -m 'Add b as you' --user you#foo.com
hg update 0
hg branch stable
hg graft --user 3rd#bar.com --force 1
hg log --graph
# changeset: 2:3078a4888a8a
| branch: stable
| tag: tip
| parent: 0:f7fa0d60eaf2
| user: 3rd#bar.com
| date: Fri Apr 28 20:07:35 2017 +0200
| summary: Add b as you
|
| o changeset: 1:e12471b861d6
|/ user: you#foo.com
| date: Fri Apr 28 20:07:35 2017 +0200
| summary: Add b as you
|
o changeset: 0:f7fa0d60eaf2
user: This Is Me me#me.com
date: Fri Apr 28 20:06:42 2017 +0200
summary: Add a as myself
If you think about it, it is less shocking than what is seems (I am not saying it is not a problem, mind you).
Mercurial has an extension to perform PGP signatures which might help, but not after the fact and requires a certain setup.
To have detailed explanation, have a look at CommitSigningPlan, although I don't know the status.
To my knowledge, monotone was a distributed VCS system designed to solve this kind of problems, I am not sure whether it is still developed.
I would finish with a philosophical observation: if a project has to protect itself from this kind of problems (an authorised developer impersonating another), then maybe that project has other problems... Again, this doesn't mean that authenticating a commit is not important.
Related
This question already has answers here:
Undo an accidental hg strip?
(3 answers)
Closed 3 years ago.
I have this Mercurial repository where I keep a counter:
$ echo 1 > count
$ hg add count
$ hg com -m 'incrementing to 1'
$ echo 2 > count
$ hg com -m 'incrementing to 2'
So far so good, but then I committed a mistake:
$ hg com -m 'incrementing to 3'
So I use hg strip to revert this last commit:
$ hg strip --keep -r -2
saved backup bundle to /home/adam/sandbox/count/.hg/strip-backup/bda856a578bf-ff2b025f-backup.hg
Unbeknownst to me, I have committed another, bigger mistake! I stripped the two topmost commits, and I just wanted to strip the topmost one:
$ hg log
changeset: 0:7b5533cf962a
tag: tip
user: Adam Victor Nazareth Brandizzi <brandizzi#gmail.com>
date: Wed May 15 08:00:27 2019 -0300
summary: incrementing to 1
How I get my commits back?
NOTE: this is a contrived example of a case were I needed to use hg strip. No need to wasting time pointing out there are alternatives etc.
As I've learned from this message in Mercurial's mailing list, the solution is quite straightforward. Note that when I ran hg strip --keep -r -2 I got this line in the output:
saved backup bundle to /home/adam/sandbox/count/.hg/strip-backup/bda856a578bf-ff2b025f-backup.hg
So, basically, Mercurial made a backup of the original history! Now I just need to pull from it:
$ hg pull /home/adam/sandbox/count/.hg/strip-backup/bda856a578bf-ff2b025f-backup.hg
pulling from /home/adam/sandbox/count/.hg/strip-backup/bda856a578bf-ff2b025f-backup.hg
searching for changes
adding changesets
adding manifests
adding file changes
added 2 changesets with 2 changes to 1 files
(run 'hg update' to get a working copy)
$ hg update
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
My file is back to the original state...
$ cat count
66
...as well as my history:
$ hg log
changeset: 2:fc4d1cc18a4b
tag: tip
user: Adam Victor Nazareth Brandizzi <brandizzi#gmail.com>
date: Wed May 15 08:00:51 2019 -0300
summary: incrementing to 3
changeset: 1:bda856a578bf
user: Adam Victor Nazareth Brandizzi <brandizzi#gmail.com>
date: Wed May 15 08:00:38 2019 -0300
summary: incrementing to 2
changeset: 0:7b5533cf962a
user: Adam Victor Nazareth Brandizzi <brandizzi#gmail.com>
date: Wed May 15 08:00:27 2019 -0300
summary: incrementing to 1
Now I can call the right strip command (hg strip --keep -r -1).
What if we do not have the backup file name anymore?
You may have lost the backup file name (it did happen to me!) but you can find it in $YOUR_REPO/.hg/strip-backup. If you have many backups, just list them sorted by time, descending:
$ ls -tl .hg/strip-backup/
total 4
-rw-rw-r-- 1 adam adam 754 May 15 08:10 bda856a578bf-ff2b025f-backup.hg
-rw-rw-r-- 1 adam adam 754 May 15 08:02 02ac79859dd0-0902f53b-backup.hg
The last one is probably the one you want.
In HG, is there any command such that i can get the file content of the file from another branch without switching/checkout to the particular branch?
Similar to the other answer, you can use the cat command but in a slightly different way:
hg cat --rev=11204 path/to/file
This will pick the file from revision #11204 which can be any branch.
You may want to add the --output switch lets you use whatever filename and/or location you want:
hg cat --output=C:/new/path/to/file/filename#11204.ext --rev=11204 path/to/file
If you are using TortoiseHG, you can use the "save at revision" command to do this.
Steps:
Run Tortoise Workbench
Find the changeset in history which has the file revision you want (could be in any branch)
Say its changeset #abcd1234
Right click on the specific file in the file list for that changeset
Select "Save at revision..." and tell it where to put the file.
The file would typically be named filename#abcd1234.ext so that you don't mix it up with the current version.
Use the cat subcommand with the revision number of the commit you're looking for.
Here's an example. I create two branches with the contents of the file file indicating which branch it's on. Then I use cat to examine the contents on both branches
% hg init foo
% cd foo
% echo "default branch" > file
% hg add file
% hg ci -m 'default' file
% echo "default 2nd rev" > file
% hg ci -m 'default 2nd rev' file
% hg glog
# changeset: 1:305b2b5ccbd9
| tag: tip
| user: dj
| date: Mon Sep 17 14:11:20 2018 -0400
| summary: default 2nd rev
|
o changeset: 0:6d22c68d8abc
user: dj
date: Mon Sep 17 14:10:56 2018 -0400
summary: default
% hg co -r 0
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
% echo "new branch" > file
% hg branch 'new branch'
marked working directory as branch new branch
(branches are permanent and global, did you want a bookmark?)
% hg ci -m 'new branch'
% hg glog
# changeset: 2:4c8d2181526c
| branch: new branch
| tag: tip
| parent: 0:6d22c68d8abc
| user: dj
| date: Mon Sep 17 14:12:30 2018 -0400
| summary: new branch
|
| o changeset: 1:305b2b5ccbd9
|/ user: dj
| date: Mon Sep 17 14:11:20 2018 -0400
| summary: default 2nd rev
|
o changeset: 0:6d22c68d8abc
user: dj
date: Mon Sep 17 14:10:56 2018 -0400
summary: default
% hg branches
new branch 2:4c8d2181526c
default 1:305b2b5ccbd9
% hg cat -r 2 file
new branch
% hg cat -r 1 file
default 2nd rev
Folks, I need your help!
I tried to push my hg repository to bitbucket for the first time. It didn't work and I thought this was because the project is to huge. Therefore, I wanted to push only one single file.
Since I did "hg add *" before, I wanted to revoke this, and typed "hg remove *" and now it DELETED FILES ON MY COMPUTER. But not all of them, only some...
I need these files back, how do I do it? Please tell me they're not gone, please please please.
Thank you so much for your help!!
This is my command history:
518 hg commit commit_test.txt -m "first commit"
519 hg add commit_test.txt
520 hg commit -m "test"
521 ls -ll
522 ls -la
523 cd .hg/
524 ls
525 ls -la
526 pico hgrc
527 cd ..
528 hg status
529 hg add commit_test.txt~
530 hg add commit_test.txt
531 hg commit -m "blabla"
532 hg push
533 hg add commit_test.txt
534 hg commit -m "maaan"
535 hg status
536 hg remove *
537 hg status
538 hg commit -m "bla"
539 ls
540 hg add test.txt
541 hg commit -m "test"
542 hg push
543 hg revert
544 hg revert --all
545 history
546 hg add *
547 hg add -r *
548 hg help add
549 hg add -S *
550 cd gui_relabel/
551 hg add *
552 cd images/
553 hg add *
554 cd ..
555 hg revert all
556 hg revert *
557 history
Here is what hg log gives me:
$ hg log
changeset: 6:4726f671ae96
tag: tip
user: KG <...#gmail.com>
date: Wed Dec 04 12:21:30 2013 +0100
summary: test
changeset: 5:55b3158def38
user: KG <...#gmail.com>
date: Wed Dec 04 12:17:19 2013 +0100
summary: bla
changeset: 4:ae0dd836586d
user: KG <...#gmail.com>
date: Wed Dec 04 12:14:50 2013 +0100
summary: blabla
changeset: 3:0249fdc26fa7
user: KG <...#gmail.com>
date: Wed Dec 04 12:13:59 2013 +0100
summary: test
changeset: 2:40bdcf4d2104
user: KG <...#gmail.com>
date: Wed Dec 04 12:12:37 2013 +0100
summary: first commit test
changeset: 1:f9e20020ca1d
user: KG <...#gmail.com>
date: Sun Nov 10 14:54:46 2013 +0100
summary: first commit
changeset: 0:7a8edcee06ff
user: KG <...#gmail.com>
date: Mon Nov 04 20:36:41 2013 +0100
summary: blabla
Your files are not gone. Mercurial does not throw away data, that is one of the first rules of the system.
To explain what hg remove did to your files, let us look at the cases one by one. A file in your working copy can be in one out of a handful different states: it can be modified, added, removed, missing, unknown, ignored, or clean.
I've prepared a working copy that looks like this:
$ hg status --all
M a
A b
R c
! d
? e
I f
C g
The files a to g are in the seven states I mentioned above. We can now talk about what happens when you try to remove these files:
A modified file (a) is not removed:
$ hg remove a
not removing a: file is modified (use -f to force removal)
An added file (b) is also not removed:
$ hg remove b
not removing b: file has been marked for add (use forget to undo)
A removed file (c) is no longer present in the working copy, so nothing more happens.
A missing file (d) is no longer present in the working copy, so nothing more happens.
An untracked file (e) is not removed:
$ hg remove e
not removing e: file is untracked
An ignored file (f) is not removed (since it is not tracked):
$ hg remove f
not removing f: file is untracked
A clean file (g) is removed.
The only type of file that hg remove will actually remove from your working copy is a clean file. A clean file is already committed, so the content is safely stored in the repository. You can get it back with hg revert:
$ hg revert g
$ hg status --all
M a
A b
R c
! d
? e
I f
C g
The file g is back with the same content as it had before you removed it.
It looks like you could run
hg backout 5
You can read more about backout if you like
I am working with a repository whose root has moved around some in its history (started at trunk/, moved to subproject/trunk). Right now I can either use hgsubversion to work with all the history up to the point when it moved to subproject/trunk (see https://bitbucket.org/durin42/hgsubversion/issue/135/move-tracking), or I can use hg convert or rebase to splice together the histories into one cohesive repository.
After splicing and calling hg svn rebuildmeta, hgsubversion is all confused. New revisions in the svn repository are pulled into a branch called "../".
Basically, I'm wondering if it's possible to tell hgsubversion to use a certain svn revision as its reference point, only attempting to sync up the histories from that point forward?
Here is a small test illustrating the issue (sorry for the DOS commands)
C:\hgtest>svnadmin create svnrepo
C:\hgtest>svn co file:///C:/hgtest/svnrepo svncheckout
Checked out revision 0.
C:\hgtest>cd svncheckout
C:\hgtest\svncheckout>mkdir trunk/
The syntax of the command is incorrect.
C:\hgtest\svncheckout>svn mkdir trunk
A trunk
C:\hgtest\svncheckout>cd trunk
C:\hgtest\svncheckout\trunk>echo "Test file version 1" > testfile.txt
C:\hgtest\svncheckout\trunk>cd ..
C:\hgtest\svncheckout>svn add trunk\testfile.txt
A trunk\testfile.txt
C:\hgtest\svncheckout>svn ci -m "Original version in trunk configuration"
Adding trunk
Adding trunk\testfile.txt
Transmitting file data .
Committed revision 1.
C:\hgtest\svncheckout>svn mkdir subproject
A subproject
C:\hgtest\svncheckout>svn mv trunk subproject
A subproject\trunk
D trunk
D trunk\testfile.txt
C:\hgtest\svncheckout>svn ci -m "Moved trunk to subproject/trunk"
Adding subproject
Adding subproject\trunk
Deleting trunk
Committed revision 2.
C:\hgtest\svncheckout>echo ". Adding some text to distinguish the subproject/trunk version of this file" >> subproject\trunk\testfile.txt
C:\hgtest\svncheckout>svn ci -m "Final version of testfile.txt"
Sending subproject\trunk\testfile.txt
Transmitting file data .
Committed revision 3.
C:\hgtest\svncheckout>svn log subproject\trunk\testfile.txt
------------------------------------------------------------------------
r3 | kmahan | 2012-02-17 09:18:23 -0800 (Fri, 17 Feb 2012) | 1 line
Final version of testfile.txt
------------------------------------------------------------------------
r2 | kmahan | 2012-02-17 09:17:40 -0800 (Fri, 17 Feb 2012) | 1 line
Moved trunk to subproject/trunk
------------------------------------------------------------------------
r1 | kmahan | 2012-02-17 09:14:46 -0800 (Fri, 17 Feb 2012) | 1 line
Original version in trunk configuration
------------------------------------------------------------------------
C:\hgtest>hg clone svn://localhost:22222/subproject/trunk hgrepo
[r2] kmahan: Moved trunk to subproject/trunk
[r3] kmahan: Final version of testfile.txt
pulled 2 revisions
updating to branch default
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
C:\hgtest>cd hgrepo
C:\hgtest\hgrepo>dir
Volume in drive C is OSDisk
Volume Serial Number is 74C7-4865
Directory of C:\hgtest\hgrepo
02/17/2012 09:30 AM <DIR> .
02/17/2012 09:30 AM <DIR> ..
02/17/2012 09:30 AM <DIR> .hg
02/17/2012 09:30 AM 104 testfile.txt
1 File(s) 104 bytes
3 Dir(s) 1,705,932,423,168 bytes free
C:\hgtest\hgrepo>hg log --follow testfile.txt
changeset: 1:eae92a250a90
tag: tip
user: kmahan#b3f284a4-0405-ad4c-b974-dac5aa90a095
date: Fri Feb 17 17:18:23 2012 +0000
summary: Final version of testfile.txt
changeset: 0:10c6ad198001
user: kmahan#b3f284a4-0405-ad4c-b974-dac5aa90a095
date: Fri Feb 17 17:17:40 2012 +0000
summary: Moved trunk to subproject/trunk
C:\hgtest>hg clone svn://localhost:22222/trunk -r 1 original-location
[r1] kmahan: Original version in trunk configuration
pulled 1 revisions
updating to branch default
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
C:\hgtest>cd hgrepo
C:\hgtest\hgrepo>hg pull -f ..\original-location
pulling from ..\original-location
searching for changes
warning: repository is unrelated
requesting all changes
adding changesets
adding manifests
adding file changes
added 1 changesets with 0 changes to 1 files (+1 heads)
(run 'hg heads' to see heads, 'hg merge' to merge)
C:\hgtest\hgrepo>hg log
changeset: 2:f968692b6301
tag: tip
parent: -1:000000000000
user: kmahan#b3f284a4-0405-ad4c-b974-dac5aa90a095
date: Fri Feb 17 17:14:46 2012 +0000
summary: Original version in trunk configuration
changeset: 1:eae92a250a90
user: kmahan#b3f284a4-0405-ad4c-b974-dac5aa90a095
date: Fri Feb 17 17:18:23 2012 +0000
summary: Final version of testfile.txt
changeset: 0:10c6ad198001
user: kmahan#b3f284a4-0405-ad4c-b974-dac5aa90a095
date: Fri Feb 17 17:17:40 2012 +0000
summary: Moved trunk to subproject/trunk
C:\hgtest\hgrepo>hg rebase -s 0 -d 2
saved backup bundle to C:\hgtest\hgrepo\.hg\strip-backup\10c6ad198001-backup.hg
C:\hgtest\hgrepo>hg log
changeset: 1:ee10af28394f
tag: tip
user: kmahan#b3f284a4-0405-ad4c-b974-dac5aa90a095
date: Fri Feb 17 17:18:23 2012 +0000
summary: Final version of testfile.txt
changeset: 0:f968692b6301
user: kmahan#b3f284a4-0405-ad4c-b974-dac5aa90a095
date: Fri Feb 17 17:14:46 2012 +0000
summary: Original version in trunk configuration
C:\hgtest\hgrepo>hg svn rebuildmeta
C:\hgtest\hgrepo>hg pull
pulling from svn://localhost:22222/subproject/trunk
[r2] kmahan: Moved trunk to subproject/trunk
Marked branch ../ as closed.
[r3] kmahan: Final version of testfile.txt
no changes found
C:\hgtest\hgrepo>echo "Here's some more text" >> testfile.txt
C:\hgtest\hgrepo>hg ci -m "Test commit from mercurial side"
C:\hgtest\hgrepo>hg glog
o changeset: 5:a0e38c8fcfaf
| branch: ../
| tag: tip
| user: kmahan#b3f284a4-0405-ad4c-b974-dac5aa90a095
| date: Fri Feb 17 17:43:38 2012 +0000
| summary: Added new text from the svn side
|
o changeset: 4:39fe2d8d743c
| branch: ../
| parent: 0:f968692b6301
| user: kmahan#b3f284a4-0405-ad4c-b974-dac5aa90a095
| date: Fri Feb 17 17:18:23 2012 +0000
| summary: Final version of testfile.txt
|
| o changeset: 3:4a494fcf85f1
|/ branch: ../
| parent: 0:f968692b6301
| user: kmahan#b3f284a4-0405-ad4c-b974-dac5aa90a095
| date: Fri Feb 17 17:17:40 2012 +0000
| summary: Moved trunk to subproject/trunk
|
| # changeset: 2:547ed469c516
| | user: Kyle Mahan <kmahan#redacted.com>
| | date: Fri Feb 17 09:33:07 2012 -0800
| | summary: Test commit from mercurial side
| |
| o changeset: 1:ee10af28394f
|/ user: kmahan#b3f284a4-0405-ad4c-b974-dac5aa90a095
| date: Fri Feb 17 17:18:23 2012 +0000
| summary: Final version of testfile.txt
|
o changeset: 0:f968692b6301
user: kmahan#b3f284a4-0405-ad4c-b974-dac5aa90a095
date: Fri Feb 17 17:14:46 2012 +0000
summary: Original version in trunk configuration
Yes, but it'll be a manual process. You'll need to find the high water mark revision for each branch and record it in the metadata files (the names of which escape me at the moment). At that point, things should mostly work.
Note: this is a theory. I have high confidence that it should work based on my memory of the code, but I've never tested it.
Basically, I'm wondering if it's possible to tell hgsubversion to use a certain svn revision as its reference point, only attempting to sync up the histories from that point forward?
If I understood you correctly, you wanted --startrev option for clone command. From hg help subversion
Sometimes, past repository history is of little or no interest, and
all one wants is to start from today and work forward. Using
"--startrev HEAD" causes the initial clone to only convert the latest
revision; later pulls will convert all subsequent revisions. Please
note that this only works for single-directory clones
Let's say I have this:
hg init
touch a
hg add a
hg commit -m a
touch b
hg add b
hg commit -m b
hg up -r 0
touch c
hg add c
hg commit -m c
Now I will have multiple heads, because of the last commit. If, for example I want to keep the last head, the one created by commit c ( effectively discarding b, and all other commits made after the first ) , how could I do it? I played a little with mq's strip command, and I'm able to achieve what I want, but I'd like to know if there's another way.
Yes, there is another way. From your example above, the output of hg glog looks a bit like this:
# changeset: 2:925573c7103c
| tag: tip
| parent: 0:4fe26dfe856d
| user: Joel B Fant
| date: Thu Jul 28 23:20:45 2011 -0400
| summary: c
|
| o changeset: 1:9dc928176506
|/ user: Joel B Fant
| date: Thu Jul 28 23:20:24 2011 -0400
| summary: b
|
o changeset: 0:4fe26dfe856d
user: Joel B Fant
date: Thu Jul 28 23:20:12 2011 -0400
summary: a
If you clone test but specify a revision, it will only clone that revision and its ancestors. So if your repo's directory is TwoHeadsMightNotBeBetter, you can go to its parent directory and issue:
hg clone TwoHeadsMightNotBeBetter OneHeadIsFine -r 925573c7103c
I specified changeset id in that, but you could also use -r 2 instead, or even -r tip since it is currently the tip of that repo. Now when you go into the new clone and do hg glog, you have only one head:
# changeset: 1:925573c7103c
| tag: tip
| user: Joel B Fant
| date: Thu Jul 28 23:20:45 2011 -0400
| summary: c
|
o changeset: 0:4fe26dfe856d
user: Joel B Fant
date: Thu Jul 28 23:20:12 2011 -0400
summary: a
If you had 3 heads and wanted to keep 2, it would be a little different. You'd have to clone one of them with -r and the also specify -r on hg pull to pull specific branches.
You can also perform a dummy merge of the changeset containing b (changeset 1 in this case):
$ hg --config ui.merge=internal:fail merge 1
resolving manifests
getting b
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
(branch merge, don't forget to commit)
$ hg revert --all --no-backup --rev .
removing b
$ hg status
R b
$ hg commit -m "Dummy merge -- eliminate b"
committed changeset 3:c163151f19df
$ ls
a c
Note that in this case you haven't rewritten any history or created any new repos -- particularly important if b had already been pushed to a centralized repo and pulled by others.