Mercurial: Difference between revisions
(→hg) |
(→hg) |
||
(37 intermediate revisions by the same user not shown) | |||
Line 1: | Line 1: | ||
= Misc = |
|||
== hg == |
== hg == |
||
* [[Deciding which Source Management Tool to use]] |
|||
=== Intro === |
|||
It is VERY important you keep in mind that Mercurial has a repository and a working directory and these are different things. |
|||
As always under Windows replace in paths '/' with '\' and ' with ". |
|||
Example: |
|||
mkdir d1 |
|||
cd d1 |
|||
hg init |
|||
echo [ui] > .hg/hgrc |
|||
echo username = ItsaMea >> .hg/hgrc |
|||
echo "test" > file1 |
|||
hg add file1 |
|||
hg commit -m 'adding test file' |
|||
cd .. |
|||
mkdir d2 |
|||
cd d2 |
|||
hg clone ../d1 . |
|||
dir |
|||
cd .. |
|||
cd d1 |
|||
echo "test2" > file2 |
|||
hg add file2 |
|||
hg commit -m 'adding test file' |
|||
hg push ../d2 |
|||
hg status |
|||
dir |
|||
cd .. |
|||
cd d2 |
|||
dir |
|||
hg status |
|||
hg update |
|||
dir |
|||
As you can see, the changes in repository d1 are only seen in the working directory of repository2 after you do a push or pull AND update. The update will get the changes in repository d2 to the working directory of repository2. Depending on the circumstances, you will need to do a merge before you can push/pull. |
|||
So in this example we had four items to think about: |
|||
* Repository d1 |
|||
* Working directory of repository d1 |
|||
* Repository d2 |
|||
* Working directory of repository d2 |
|||
If you understand that push/pull work on repositories, NOT on working directories, you will have an easier life. I did - of course - not write this paragraph because I forgot about this and did not understand something happening until I thought it through. Of course not! |
|||
=== config file === |
=== config file === |
||
Line 12: | Line 59: | ||
[ui] |
[ui] |
||
username = John Doe <john@example.com> |
username = John Doe <john@example.com> |
||
=== simple use === |
|||
* create a repository |
|||
hg init |
|||
* create a file |
|||
echo "Hello World" > myTestFile |
|||
* prepare it to be used by the next commit |
|||
hg add myTestFile |
|||
* add it to the repository (under Windows: use " instead of ' for the comment) |
|||
hg commit -m 'adding a test file for test purposes and because testing is so tasty' |
|||
* what happened in the long long history of this repository? |
|||
hg log |
|||
* if you added the aliases I mention somewhere on this page, try |
|||
hg ll |
|||
* create another file |
|||
echo "Bye bye World" > myTestFile2 |
|||
* change the first file |
|||
echo "Hello World 2" >> myTestFile |
|||
* check the status of the files |
|||
hg status |
|||
* commit all file with changes which are already managed by the repository |
|||
hg commit -m 'committing changes ... again? Work, Work' |
|||
* check the status of the files |
|||
hg status |
|||
You will see that "hg commit" will commit all your changes to the repository. It will ignore new files until you manually add them with "hg add". |
|||
You CAN use "hg commit" and give the files you want to commit as parameters. But normally you don't want to do that. |
|||
=== Create a repository from an existing project/directory === |
|||
* go into the root for the project and call there "hg init" |
|||
cd /d my-cool-project |
|||
hg init |
|||
* create / copy a file "hgrc" inside .hg like the following |
|||
<pre> |
|||
[ui] |
|||
ssh = ssh -C |
|||
username = Super Man <SuperMan@BatsCave.net> |
|||
[alias] |
|||
logline = log --template "{node|short} | {date|isodatesec} | {author|user}: {desc|strip|firstline}\n" |
|||
ll = logline -l 10 |
|||
status = status --template status |
|||
[paths] |
|||
default = d:\data\repos\mercurial\SuperMan |
|||
backup = d:\data\repos\mercurial\SuperMan |
|||
r-netbook = ssh://r-netbook/work/SuperMan/ |
|||
r-laptop = ssh://r-laptop/work/SuperMan/ |
|||
usb = P:\SuperMan |
|||
</pre> |
|||
* Consider to use the aliases |
|||
* The paths will be wrong for you, these should only give you an idea. Or 7. |
|||
* In the root of your project call "hg add ." |
|||
cd /d my-cool-project |
|||
hg add . |
|||
* commit the prepared adds (Linux uses ' instead of ", different paths too.. as always) |
|||
hg commit -m "initial adding of the project to Mercurial" |
|||
This might take a while, it is practically a copy of your current project. |
|||
Now you have a project which can use Mercurial. |
|||
But you will probably want a server version of it in your backup folder. You have something like that, right? A folder which will be used to backup everything inside from time to time? |
|||
So... you'll clone your project to the backup folder: (it is: clone <source> <target>, so do NOT forget the '.') |
|||
hg clone . D:\data\repos\mercurial\my-cool-project |
|||
You do not want your server to have a checked out working directory, nobody will ever work on the server. NEVER! |
|||
cd /d D:\data\repos\mercurial\my-cool-project |
|||
hg up null |
|||
now try |
|||
cd /d my-cool-project |
|||
hg status |
|||
hg ll |
|||
hg push |
|||
=== aliases === |
=== aliases === |
||
Line 17: | Line 139: | ||
==== mercurial command line log as one line per commit ==== |
==== mercurial command line log as one line per commit ==== |
||
Windows: |
Windows: |
||
add: |
add to .hg/hgrc: |
||
[alias] |
[alias] |
||
logline = log --template "{node|short} | {date|isodatesec} | {author|user}: {desc|strip|firstline}\n" |
logline = log --template "{node|short} | {date|isodatesec} | {author|user}: {desc|strip|firstline}\n" |
||
ll = logline |
|||
Linux: |
Linux: |
||
add: (the only difference to Windows is " vs ' |
add to .hg/hgrc: (the only difference to Windows is " vs ' |
||
[alias] |
[alias] |
||
logline = log --template '{node|short} | {date|isodatesec} | {author|user}: {desc|strip|firstline}\n' |
logline = log --template '{node|short} | {date|isodatesec} | {author|user}: {desc|strip|firstline}\n' |
||
==== Weird formatting of status output ==== |
|||
If you get something which looks like bad readable links if you do |
|||
hg status |
|||
then you probably don't want that. |
|||
I do not understand the reason for it and I am not sure my "solution" is the correct way to do it. But it works: |
|||
[alias] |
|||
status = status --template status |
|||
=== ssh === |
=== ssh === |
||
Line 64: | Line 194: | ||
If you clone a repository, your default is of course the source of the clone. |
If you clone a repository, your default is of course the source of the clone. |
||
==== clone via ssh to remote ==== |
|||
Somehow the Windows .ssh\config was completely ignored. I had to start the putty pagent with the private key needed and give the data manually, not via the 'hg paths' shortcut. |
|||
THEN I could use |
|||
hg clone . ssh://username@127.0.0.1:20023/work/src/ |
|||
This created a repository on that system. Don't forget to |
|||
hg update |
|||
if you want to see the data. You will want to do something about .hg/hgrc too. |
|||
(In the example above I am using the local ip and a weird port because I ssh into a locally running VirtualBox with my development environment.) |
|||
=== copy/move === |
=== copy/move === |
||
Line 77: | Line 216: | ||
If you want it to be empty, for example because it is just like a server, no need need for a working directory with checkout: |
If you want it to be empty, for example because it is just like a server, no need need for a working directory with checkout: |
||
hg |
hg update null |
||
Only the . |
Only the .hg directory will remain. |
||
== TortoiseHG == |
== TortoiseHG == |
||
=== Why does hg not work? === |
=== Why does hg not work? === |
||
After you installed TortoiseHG, add the path to the install directory of TortoiseHG to the PATH variable. (Start/Settings/System/About/System Info/Advanced system settings/Environment Variables...) |
After you installed TortoiseHG, add the path to the install directory of TortoiseHG to the PATH variable. (Start/Settings/System/About/System Info/Advanced system settings/Environment Variables...) |
||
== ignore == |
|||
[https://www.selenic.com/mercurial/hgignore.5.html (source)] |
|||
In the root of the repository you can put a file ".hgignore". |
|||
Here you can use normal ("glob") patterns or regular expressions, somehow. |
|||
For glob: |
|||
syntax: glob |
|||
*.aux |
|||
*.log |
|||
*.out |
|||
*.synctex.gz |
|||
From now on you will not see untracked files with these extensions if you use |
|||
hg status |
|||
But if you use |
|||
hg status -A |
|||
Then you'll see the files with an "I" for ignored. |
|||
== Manage hgrc with Mercurial == |
|||
Everything in .hg does NOT have a history in Mercurial. |
|||
Depending on your circumstances, you want the history of hgrc or even be able to copy/paste another hgrc to your current installation without a hassle. |
|||
You can do it: |
|||
* in the main directory of your Mercurial repository create a directory called ".hg-configs-managed". |
|||
* move your current .hg/hgrc to .hg-configs-managed/hgrc-MY-CORPORATION-PC01 |
|||
* create a link .hg/hgrc which points to .hg-configs-managed/hgrc-MY-CORPORATION-PC01 |
|||
* put .hg-configs-managed/hgrc-MY-CORPORATION-PC01 into Mercurial ("hg add...") |
|||
* repeat this for every installation, so you'll get a lot of files in .hg-configs-managed but only one hgrc in .hg |
|||
=== Create the link with Linux === |
|||
cd .hg |
|||
ln -s ../.hg-configs-managed/hgrc-MY-CORPORATION-PC01 hgrc |
|||
=== Create the link with Windows 10 === |
|||
cd .hg |
|||
mklink /H hgrc ..\.hg-configs-managed\hgrc-MY-CORPORATION-PC01 |
|||
=== Misc === |
|||
Mercurial does not recognize changes from hardlinks for files outside the repository. |
|||
Hardlinks need no (less?) rights, so it should be ok for everyone as long as you use them only inside the repository. <br> |
|||
If you have the needed rights and want to use links for [[Setup your system for an easy backup|lazy backups]], consider using Softlinks (mklink without /H), because you want to be consistent and not have to think about which files got a softlink and which ones got a hardlink. <br> |
|||
On the other side, knowing that THIS link is always a hardlink and every person in your team can use it without needing more rights is good too. So it totally depends on your environment and your goals. |
|||
== Questions == |
|||
=== Get a managed file back which I deleted === |
|||
I deleted a file and just want Mercurial to get it again: |
|||
hg revert <file> |
|||
=== Diff abort with "not under root" === |
|||
* pull/push |
|||
cd myLocalRepository |
|||
hg pull remoteRepository |
|||
* diff |
|||
cd myLocalRepository |
|||
hg diff remoteRepository |
|||
ERROR |
|||
Diff is mostly used for differences between revisions. And it is used for differences between files. If you just point it to a repository, chances are, the command will fail. There were cases where the command did not give me an error. But do NOT use diff as test for your connection to a remote repository. |
|||
If you need a test command, use something like |
|||
hg outgoing otherRepository |
|||
=== Remove vs. forget === |
|||
* Both remove the file from Mercurial's tracking |
|||
** "Forget" leaves the file alone, so it will just be an untracked file |
|||
** "Remove" will delete the file |
Latest revision as of 01:28, 5 August 2024
hg
Intro
It is VERY important you keep in mind that Mercurial has a repository and a working directory and these are different things. As always under Windows replace in paths '/' with '\' and ' with ".
Example:
mkdir d1 cd d1 hg init echo [ui] > .hg/hgrc echo username = ItsaMea >> .hg/hgrc echo "test" > file1 hg add file1 hg commit -m 'adding test file'
cd .. mkdir d2 cd d2 hg clone ../d1 . dir
cd .. cd d1 echo "test2" > file2 hg add file2 hg commit -m 'adding test file' hg push ../d2 hg status dir
cd .. cd d2 dir hg status hg update dir
As you can see, the changes in repository d1 are only seen in the working directory of repository2 after you do a push or pull AND update. The update will get the changes in repository d2 to the working directory of repository2. Depending on the circumstances, you will need to do a merge before you can push/pull.
So in this example we had four items to think about:
- Repository d1
- Working directory of repository d1
- Repository d2
- Working directory of repository d2
If you understand that push/pull work on repositories, NOT on working directories, you will have an easier life. I did - of course - not write this paragraph because I forgot about this and did not understand something happening until I thought it through. Of course not!
config file
- Windows: C:\Users\<User>\mercurial.ini
- Linux: ~/.hgrc
Username/Mail
If you are using the commandline, make sure to add to your config file:
[ui] username = John Doe <john@example.com>
simple use
- create a repository
hg init
- create a file
echo "Hello World" > myTestFile
- prepare it to be used by the next commit
hg add myTestFile
- add it to the repository (under Windows: use " instead of ' for the comment)
hg commit -m 'adding a test file for test purposes and because testing is so tasty'
- what happened in the long long history of this repository?
hg log
- if you added the aliases I mention somewhere on this page, try
hg ll
- create another file
echo "Bye bye World" > myTestFile2
- change the first file
echo "Hello World 2" >> myTestFile
- check the status of the files
hg status
- commit all file with changes which are already managed by the repository
hg commit -m 'committing changes ... again? Work, Work'
- check the status of the files
hg status
You will see that "hg commit" will commit all your changes to the repository. It will ignore new files until you manually add them with "hg add". You CAN use "hg commit" and give the files you want to commit as parameters. But normally you don't want to do that.
Create a repository from an existing project/directory
- go into the root for the project and call there "hg init"
cd /d my-cool-project hg init
- create / copy a file "hgrc" inside .hg like the following
[ui] ssh = ssh -C username = Super Man <SuperMan@BatsCave.net> [alias] logline = log --template "{node|short} | {date|isodatesec} | {author|user}: {desc|strip|firstline}\n" ll = logline -l 10 status = status --template status [paths] default = d:\data\repos\mercurial\SuperMan backup = d:\data\repos\mercurial\SuperMan r-netbook = ssh://r-netbook/work/SuperMan/ r-laptop = ssh://r-laptop/work/SuperMan/ usb = P:\SuperMan
- Consider to use the aliases
- The paths will be wrong for you, these should only give you an idea. Or 7.
- In the root of your project call "hg add ."
cd /d my-cool-project hg add .
- commit the prepared adds (Linux uses ' instead of ", different paths too.. as always)
hg commit -m "initial adding of the project to Mercurial"
This might take a while, it is practically a copy of your current project.
Now you have a project which can use Mercurial. But you will probably want a server version of it in your backup folder. You have something like that, right? A folder which will be used to backup everything inside from time to time?
So... you'll clone your project to the backup folder: (it is: clone <source> <target>, so do NOT forget the '.')
hg clone . D:\data\repos\mercurial\my-cool-project
You do not want your server to have a checked out working directory, nobody will ever work on the server. NEVER!
cd /d D:\data\repos\mercurial\my-cool-project hg up null
now try
cd /d my-cool-project hg status hg ll hg push
aliases
mercurial command line log as one line per commit
Windows: add to .hg/hgrc:
[alias] logline = log --template "{node|short} | {date|isodatesec} | {author|user}: {desc|strip|firstline}\n" ll = logline
Linux: add to .hg/hgrc: (the only difference to Windows is " vs '
[alias] logline = log --template '{node|short} | {date|isodatesec} | {author|user}: {desc|strip|firstline}\n'
Weird formatting of status output
If you get something which looks like bad readable links if you do
hg status
then you probably don't want that. I do not understand the reason for it and I am not sure my "solution" is the correct way to do it. But it works:
[alias] status = status --template status
ssh
Normally you will want to use the default OS ssh. So add the following to the config file:
[ui] ssh = ssh -C
The "-C" seems to enable compression. Not sure yet, but I keep it for now.
IF you can normally ssh to the other machine with
ssh v-rooster
then now you should be able to do a
hg -v push ssh://v-rooster/work/repo1/
or pull or clone or whatever you want to do.
You can give a name and/or port like this:
hg -v push ssh://user@v-rooster:port/work/repo1/
but it would make more sense to configure your port to connect correctly. Example under Windows 10, modify your C:\Users\<user>\.ssh\config
Host v-rooster HostName 1.2.3.4 User meaMario Port 22 IdentityFile C:\Users\<user>\.ssh\id_rsa-no-pw
paths
If you don't want to write the server and path all the time, add the following to the config file:
[paths] default = ssh://v-deb-dev2/work/src/ v-deb-dev1 = ssh://v-deb-dev1/work/src/ v-deb-dev2 = ssh://v-deb-dev2/work/src/ v-deb-dev3 = ssh://v-deb-dev3/work/src/
You guessed it, 'default' is the entry which is used, when you don't give a remote target. It is NOT necessary to have it as normal path AND default, but I like it that way.
If you want to see these with hg:
hg paths
If you clone a repository, your default is of course the source of the clone.
clone via ssh to remote
Somehow the Windows .ssh\config was completely ignored. I had to start the putty pagent with the private key needed and give the data manually, not via the 'hg paths' shortcut. THEN I could use
hg clone . ssh://username@127.0.0.1:20023/work/src/
This created a repository on that system. Don't forget to
hg update
if you want to see the data. You will want to do something about .hg/hgrc too.
(In the example above I am using the local ip and a weird port because I ssh into a locally running VirtualBox with my development environment.)
copy/move
use
hg cp source target hg mv source target hg mv oldFile NewFile hg mv project directory
empty work directory
Normally you have all the history in the .hg directory and than a checked out version directly in the repositories root directory.
If you want it to be empty, for example because it is just like a server, no need need for a working directory with checkout:
hg update null
Only the .hg directory will remain.
TortoiseHG
Why does hg not work?
After you installed TortoiseHG, add the path to the install directory of TortoiseHG to the PATH variable. (Start/Settings/System/About/System Info/Advanced system settings/Environment Variables...)
ignore
In the root of the repository you can put a file ".hgignore". Here you can use normal ("glob") patterns or regular expressions, somehow. For glob:
syntax: glob *.aux *.log *.out *.synctex.gz
From now on you will not see untracked files with these extensions if you use
hg status
But if you use
hg status -A
Then you'll see the files with an "I" for ignored.
Manage hgrc with Mercurial
Everything in .hg does NOT have a history in Mercurial. Depending on your circumstances, you want the history of hgrc or even be able to copy/paste another hgrc to your current installation without a hassle. You can do it:
- in the main directory of your Mercurial repository create a directory called ".hg-configs-managed".
- move your current .hg/hgrc to .hg-configs-managed/hgrc-MY-CORPORATION-PC01
- create a link .hg/hgrc which points to .hg-configs-managed/hgrc-MY-CORPORATION-PC01
- put .hg-configs-managed/hgrc-MY-CORPORATION-PC01 into Mercurial ("hg add...")
- repeat this for every installation, so you'll get a lot of files in .hg-configs-managed but only one hgrc in .hg
Create the link with Linux
cd .hg ln -s ../.hg-configs-managed/hgrc-MY-CORPORATION-PC01 hgrc
Create the link with Windows 10
cd .hg mklink /H hgrc ..\.hg-configs-managed\hgrc-MY-CORPORATION-PC01
Misc
Mercurial does not recognize changes from hardlinks for files outside the repository.
Hardlinks need no (less?) rights, so it should be ok for everyone as long as you use them only inside the repository.
If you have the needed rights and want to use links for lazy backups, consider using Softlinks (mklink without /H), because you want to be consistent and not have to think about which files got a softlink and which ones got a hardlink.
On the other side, knowing that THIS link is always a hardlink and every person in your team can use it without needing more rights is good too. So it totally depends on your environment and your goals.
Questions
Get a managed file back which I deleted
I deleted a file and just want Mercurial to get it again:
hg revert <file>
Diff abort with "not under root"
- pull/push
cd myLocalRepository hg pull remoteRepository
- diff
cd myLocalRepository hg diff remoteRepository ERROR
Diff is mostly used for differences between revisions. And it is used for differences between files. If you just point it to a repository, chances are, the command will fail. There were cases where the command did not give me an error. But do NOT use diff as test for your connection to a remote repository.
If you need a test command, use something like
hg outgoing otherRepository
Remove vs. forget
- Both remove the file from Mercurial's tracking
- "Forget" leaves the file alone, so it will just be an untracked file
- "Remove" will delete the file