367 lines
21 KiB
HTML
367 lines
21 KiB
HTML
|
<!DOCTYPE html>
|
||
|
<html lang='en'><head><meta charset='utf-8' /><meta name='pinterest' content='nopin' /><link href='../../../../static/css/style.css' rel='stylesheet' type='text/css' /><link href='../../../../static/css/print.css' rel='stylesheet' type='text/css' media='print' /><title>A Guide to Branching in Mercurial / Steve Losh</title></head><body><header><a id='logo' href='https://stevelosh.com/'>Steve Losh</a><nav><a href='../../../index.html'>Blog</a> - <a href='https://stevelosh.com/projects/'>Projects</a> - <a href='https://stevelosh.com/photography/'>Photography</a> - <a href='https://stevelosh.com/links/'>Links</a> - <a href='https://stevelosh.com/rss.xml'>Feed</a></nav></header><hr class='main-separator' /><main id='page-blog-entry'><article><h1><a href='index.html'>A Guide to Branching in Mercurial</a></h1><p class='date'>Posted on August 30th, 2009.</p><p>I've been hanging out in the <a href="irc://irc.freenode.net/#mercurial">#mercurial</a> and <a href="irc://irc.freenode.net/#bitbucket">#bitbucket</a>
|
||
|
channels on freenode a lot lately, and I've noticed a topic that comes up a
|
||
|
lot is "how does <a href="http://mercurial-scm.org/">Mercurial</a>'s branching differ from <a href="http://git-scm.com/">git</a>'s branching?"</p>
|
||
|
|
||
|
<p>A while ago <a href="http://litanyagainstfear.com/">Nick Quaranto</a> and I were talking about Mercurial and git's
|
||
|
branching models on Twitter and I wrote out a <a href="http://a.longreply.com/178502">quick longreply</a> about
|
||
|
the main differences. Since then I've pointed some git users toward that post
|
||
|
and they seemed to like it, so I figured I'd turn it into something a bit more
|
||
|
detailed.</p>
|
||
|
|
||
|
<p><strong>Disclaimer:</strong> this post is not intended to be a guide to the commands used
|
||
|
for working with Mercurial. It is only meant to be a guide to the <em>concepts</em>
|
||
|
behind the branching models. For more information on daily use and commands,
|
||
|
the <a href="http://hgbook.red-bean.com/">hg book</a> is a great resource (if you find it useful, please
|
||
|
<a href="http://search.barnesandnoble.com/Mercurial/Bryan-OSullivan/e/9780596800673/?itm=1">buy</a> a paper copy to support Bryan and have a printed copy of the
|
||
|
<a href="http://twitpic.com/cwod4">best editing fail of all time</a>).</p>
|
||
|
|
||
|
<ol class="table-of-contents"><li><a href="index.html#s1-prologue">Prologue</a></li><li><a href="index.html#s2-branching-with-clones">Branching with Clones</a><ol><li><a href="index.html#s3-advantages">Advantages</a></li><li><a href="index.html#s4-disadvantages">Disadvantages</a></li><li><a href="index.html#s5-comparison-to-git">Comparison to git</a></li></ol></li><li><a href="index.html#s6-branching-with-bookmarks">Branching with Bookmarks</a><ol><li><a href="index.html#s7-advantages">Advantages</a></li><li><a href="index.html#s8-disadvantages">Disadvantages</a></li><li><a href="index.html#s9-comparison-to-git">Comparison to git</a></li></ol></li><li><a href="index.html#s10-branching-with-named-branches">Branching with Named Branches</a><ol><li><a href="index.html#s11-advantages">Advantages</a></li><li><a href="index.html#s12-disadvantages">Disadvantages</a></li><li><a href="index.html#s13-comparison-to-git">Comparison to git</a></li></ol></li><li><a href="index.html#s14-branching-anonymously">Branching Anonymously</a><ol><li><a href="index.html#s15-advantages">Advantages</a></li><li><a href="index.html#s16-disadvantages">Disadvantages</a></li><li><a href="index.html#s17-comparison-to-git">Comparison to git</a></li></ol></li><li><a href="index.html#s18-one-more-difference-between-mercurial-and-git">One More Difference Between Mercurial and git</a></li><li><a href="index.html#s19-conclusion">Conclusion</a></li></ol>
|
||
|
|
||
|
<h2 id="s1-prologue"><a href="index.html#s1-prologue">Prologue</a></h2>
|
||
|
|
||
|
<p>Before I start explaining the different branching models, here's a simple
|
||
|
repository I'll use as an example:</p>
|
||
|
|
||
|
<p><img class="diagram" src="../../../../static/images/blog/2009/08/branch-base.png" alt="Basic Repository"></p>
|
||
|
|
||
|
<p>The repository is in the <code>~/src/test-project</code> folder. It has three changesets
|
||
|
in it: numbers 0, 1 and 2.</p>
|
||
|
|
||
|
<p><strong>For git users:</strong> each changeset in a Mercurial repository has a hash as an
|
||
|
identifier, just like with git. However, Mercurial also assigns numbers to
|
||
|
each changeset in a repository. The numbers are <em>only</em> for that local
|
||
|
repository — two clones might have different numbers assigned to different
|
||
|
changesets depending on the order of pulls/pushes/etc. They're just there for
|
||
|
convenience while you're working with a repository.</p>
|
||
|
|
||
|
<p>The default branch name in Mercurial is "default". Don't worry about what that
|
||
|
means for now, we'll get to it. I'm mentioning it because there's a little
|
||
|
<code>default</code> marker in the diagram.</p>
|
||
|
|
||
|
<p>In all of these diagrams, a marker like that with a dashed border doesn't
|
||
|
actually exist as an object anywhere. Those are special names that you can use
|
||
|
to identify a changeset instead of the hash or number — Mercurial will
|
||
|
calculate the revision on the fly.</p>
|
||
|
|
||
|
<p>For now, ignore the <code>default</code> marker. I've colored it grey in each of the
|
||
|
diagrams where it doesn't matter.</p>
|
||
|
|
||
|
<h2 id="s2-branching-with-clones"><a href="index.html#s2-branching-with-clones">Branching with Clones</a></h2>
|
||
|
|
||
|
<p>The slowest, safest way to create a branch with Mercurial is to make a new
|
||
|
clone of the repository:</p>
|
||
|
|
||
|
<pre><code>$ cd ~/src
|
||
|
$ hg clone test-project test-project-feature-branch </code></pre>
|
||
|
|
||
|
<p>Now you've got two copies of the repository. You can commit separately in each
|
||
|
one and push/pull changesets between them as often as you like. Once you've
|
||
|
made some changes in each one, the result might look like this:</p>
|
||
|
|
||
|
<p><img class="diagram" src="../../../../static/images/blog/2009/08/branch-clone.png" alt="Branching with Clones"></p>
|
||
|
|
||
|
<p>We've got two copies of the repository. Both contain the changesets that
|
||
|
existed at the time we branched/cloned. If we push from <code>test-project</code> into
|
||
|
<code>test-project-feature-branch</code> the "Fix a critical bug" changeset will be
|
||
|
pushed over.</p>
|
||
|
|
||
|
<p><strong>For git users:</strong> Remember how I mentioned that the changeset numbers are
|
||
|
local to a repository? We can see this clearly here — there are two different
|
||
|
changesets with the number 3. The numbers are <em>only</em> used while working inside
|
||
|
a single repository. For pushing, pulling, or talking to other people you
|
||
|
should use the hashes.</p>
|
||
|
|
||
|
<h3 id="s3-advantages"><a href="index.html#s3-advantages">Advantages</a></h3>
|
||
|
|
||
|
<p>Cloning is a very safe way of creating a branch. The two repositories are
|
||
|
completely isolated until you push or pull, so there's no danger of breaking
|
||
|
anything in one branch when you're working in another.</p>
|
||
|
|
||
|
<p>Discarding a branch you don't want any more is <em>very</em> easy with cloned
|
||
|
branches. It's as simple as <code>rm -rf test-project-feature-branch</code>. There's no
|
||
|
need to mess around with editing repository history, you just delete the damn
|
||
|
thing.</p>
|
||
|
|
||
|
<h3 id="s4-disadvantages"><a href="index.html#s4-disadvantages">Disadvantages</a></h3>
|
||
|
|
||
|
<p>Creating a branch by cloning locally is slower than the other methods, though
|
||
|
Mercurial will use hardlinks when cloning if your OS supports them (most do)
|
||
|
so it won't be <em>too</em> slow.</p>
|
||
|
|
||
|
<p>However, the clone branching method can really slow things down when other
|
||
|
developers (not located nearby) want to work on the project. If you publish
|
||
|
two branches as separate repositories (such as <code>stable</code> and <code>version-2</code>),
|
||
|
contributors will have to clone down <em>both</em> repositories through the internet
|
||
|
if they want to work on both branches. That can take a lot of extra time,
|
||
|
depending on the repository size and bandwidth.</p>
|
||
|
|
||
|
<p>It can become especially wasteful if, for example, there are 10,000 changesets
|
||
|
before the branch point and maybe 100 per branch after. Instead of pulling
|
||
|
down 10,200 changesets you need to pull down 20,200. If you want to work on
|
||
|
three different branches, you're pulling down 30,300 instead of 10,300.</p>
|
||
|
|
||
|
<p>There is a way to avoid this large download cost, as pointed out by Guido
|
||
|
Ostkamp and timeless_mbp in <a href="irc://irc.freenode.net/#mercurial">#mercurial</a>. The idea is that you clone
|
||
|
one branch down from the server, then pull <em>all</em> the branches into it, then
|
||
|
clone locally to split that repository back into branches. This avoids the
|
||
|
cost of cloning down the same changesets over and over.</p>
|
||
|
|
||
|
<p>An example of this method with three branches would look something like this:</p>
|
||
|
|
||
|
<pre><code>$ hg clone http://server/project-main project
|
||
|
$ cd project
|
||
|
$ hg pull http://server/project-branch1
|
||
|
$ hg pull http://server/project-branch2
|
||
|
$ cd ..
|
||
|
$ hg clone project project-main --rev [head of mainline branch]
|
||
|
$ hg clone project project-branch1 --rev [head of branch1]
|
||
|
$ hg clone project project-branch2 --rev [head of branch2]
|
||
|
$ rm -rf project
|
||
|
$ cd project-main
|
||
|
$ [edit .hg/hgrc file to make the default path http://server/project-main]
|
||
|
$ cd ../project-branch1
|
||
|
$ [edit .hg/hgrc to make the default path http://server/project-branch1]
|
||
|
$ cd ../project-branch2
|
||
|
$ [edit .hg/hgrc to make the default path http://server/project-branch2]</code></pre>
|
||
|
|
||
|
<p>This example assumes you know the IDs of the branch heads off the top of your
|
||
|
head, which you probably don't. You'll have to look them up.</p>
|
||
|
|
||
|
<p>It also assumes that there is only one new head per branch, when there might
|
||
|
be more. If <code>branch1</code> has two heads which are not in <code>mainline</code>, you would
|
||
|
need to look up the IDs of <em>both</em> and specify both in the clone command.</p>
|
||
|
|
||
|
<p>Another annoyance shows up when you're working on a project that relies on
|
||
|
your code being at a specific file path. If you branch by cloning you'll need
|
||
|
to rename directories (or change the file path configuration) every time you
|
||
|
want to switch branches. This might not be a common situation (most build
|
||
|
tools don't care about the absolute path to the code) but it <em>does</em> appear now
|
||
|
and then.</p>
|
||
|
|
||
|
<p>I personally don't like this method and don't use it. Others do though, so
|
||
|
it's good to understand it (Mercurial itself uses this model).</p>
|
||
|
|
||
|
<h3 id="s5-comparison-to-git"><a href="index.html#s5-comparison-to-git">Comparison to git</a></h3>
|
||
|
|
||
|
<p>Git can use this method of branching too, although I don't see it very often.
|
||
|
Technically this is the exact same thing as creating a fork on <a href="http://github.com/">GitHub</a>, but
|
||
|
most people think of "fork" and "branch" as separate concepts.</p>
|
||
|
|
||
|
<h2 id="s6-branching-with-bookmarks"><a href="index.html#s6-branching-with-bookmarks">Branching with Bookmarks</a></h2>
|
||
|
|
||
|
<p>The next way to branch is to use a bookmark. For example:</p>
|
||
|
|
||
|
<pre><code>$ cd ~/src/test-project
|
||
|
$ hg bookmark main
|
||
|
$ hg bookmark feature</code></pre>
|
||
|
|
||
|
<p>Now you've got two bookmarks (essentially a tag) for your two branches at the
|
||
|
current changeset.</p>
|
||
|
|
||
|
<p>To switch to one of these branches you can use <code>hg update feature</code> to update
|
||
|
to the tip changeset of that branch and mark yourself as working on that
|
||
|
branch. When you commit, it will move the bookmark to the newly created
|
||
|
changeset.</p>
|
||
|
|
||
|
<p><strong>Note:</strong> for more detailed information on actually using bookmarks day-to-day
|
||
|
please read the <a href="http://mercurial.selenic.com/wiki/BookmarksExtension">bookmarks page</a>. This guide is meant to show the
|
||
|
different branching models, and bookmarks have a few quirks that you should
|
||
|
know about if you're going to use them.</p>
|
||
|
|
||
|
<p>Here's what the repository would look like with this method:</p>
|
||
|
|
||
|
<p><img class="diagram" src="../../../../static/images/blog/2009/08/branch-bookmark.png" alt="Branching with Bookmarks"></p>
|
||
|
|
||
|
<p>The diagram of the changesets is pretty simple: the branch point was at
|
||
|
changeset 2 and each branch has one new changeset on it.</p>
|
||
|
|
||
|
<p>Now let's look at the markers. The <code>default</code> marker is still there, and we're
|
||
|
still going to ignore it.</p>
|
||
|
|
||
|
<p>There are two new labels in this diagram — these represent the bookmarks.
|
||
|
Notice how their outlines are <em>not</em> dashed? This is because bookmarks are
|
||
|
actual objects stored on disk, not just convenient shortcuts that Mercurial
|
||
|
will let you use.</p>
|
||
|
|
||
|
<p>When you use a bookmark name as a revision Mercurial will look up the revision
|
||
|
it points at and use that.</p>
|
||
|
|
||
|
<h3 id="s7-advantages"><a href="index.html#s7-advantages">Advantages</a></h3>
|
||
|
|
||
|
<p>Bookmarks give you a quick, lightweight way to give meaningful labels to your
|
||
|
branches.</p>
|
||
|
|
||
|
<p>You can delete them when you no longer need them. For example, if we finish
|
||
|
development of the new feature and merge the changes in the main branch, we
|
||
|
probably don't need to keep the <code>feature</code> bookmark around any more.</p>
|
||
|
|
||
|
<h3 id="s8-disadvantages"><a href="index.html#s8-disadvantages">Disadvantages</a></h3>
|
||
|
|
||
|
<p>Being lightweight can also be a disadvantage. If you delete a bookmark, then
|
||
|
look at your code a year later and wonder what all those changesets that got
|
||
|
merged into main were for, the bookmark name is gone. This probably isn't a
|
||
|
big issue if you write good changeset summaries.</p>
|
||
|
|
||
|
<p>Bookmarks are local. They do <em>not</em> get transferred during a push or pull!
|
||
|
There has been some whispering about adding this is Mercurial 1.4, but for now
|
||
|
if you want to give someone else your bookmarks you'll need to manually give
|
||
|
them the file the bookmarks are kept in.</p>
|
||
|
|
||
|
<p><strong>UPDATE:</strong> As of Mercurial 1.6 <a href="http://mercurial.selenic.com/wiki/BookmarksExtension#Working_With_Remote_Repositories">bookmarks can be pushed and
|
||
|
pulled</a> between repositories.</p>
|
||
|
|
||
|
<h3 id="s9-comparison-to-git"><a href="index.html#s9-comparison-to-git">Comparison to git</a></h3>
|
||
|
|
||
|
<p>Branching with bookmarks is very close to the way git usually handles
|
||
|
branching. Mercurial bookmarks are like git refs: named pointers to changesets
|
||
|
that move on commit.</p>
|
||
|
|
||
|
<p>The biggest difference is that git refs are transferred when pushing/pulling
|
||
|
and Mercurial bookmarks are not.</p>
|
||
|
|
||
|
<h2 id="s10-branching-with-named-branches"><a href="index.html#s10-branching-with-named-branches">Branching with Named Branches</a></h2>
|
||
|
|
||
|
<p>The third way of branching is to use Mercurial's named branches. Some people
|
||
|
prefer this method (myself included) and many others don't.</p>
|
||
|
|
||
|
<p>To create a new named branch:</p>
|
||
|
|
||
|
<pre><code>$ cd ~/src/test-project
|
||
|
$ hg branch feature</code></pre>
|
||
|
|
||
|
<p>When you commit the newly created changeset will be on the same branch as its
|
||
|
parent, unless you've used <code>hg branch</code> to mark it as being on a different one.</p>
|
||
|
|
||
|
<p>Here's what a repository using named branches might look like:</p>
|
||
|
|
||
|
<p><img class="diagram" src="../../../../static/images/blog/2009/08/branch-named.png" alt="Branching with Named Branches"></p>
|
||
|
|
||
|
<p>An important difference with this method is that the branch name is
|
||
|
permanently recorded as part of the changeset's metadata (as you can see in
|
||
|
changeset 4 in the diagram).</p>
|
||
|
|
||
|
<p><strong>Note:</strong> The default branch is called <code>default</code> and is not normally shown
|
||
|
unless you ask for verbose output.</p>
|
||
|
|
||
|
<p>Now it's time to explain those magic dashed-border labels we've been ignoring.
|
||
|
Using a branch name to specify a revision is shorthand for "the tip changeset
|
||
|
of this named branch". In this example repository:</p>
|
||
|
|
||
|
<ul>
|
||
|
<li>Running <code>hg update default</code> would update to changeset 3, which is the tip of
|
||
|
the <code>default</code> branch.</li>
|
||
|
<li>Running <code>hg update feature</code> would update to changeset 4, which is the tip of
|
||
|
the <code>feature</code> branch.</li>
|
||
|
</ul>
|
||
|
|
||
|
<p>Neither of these labels actually exist as an object anywhere on disk (like a
|
||
|
bookmark would). When you use them Mercurial calculates the appropriate
|
||
|
revision on the fly.</p>
|
||
|
|
||
|
<h3 id="s11-advantages"><a href="index.html#s11-advantages">Advantages</a></h3>
|
||
|
|
||
|
<p>The biggest advantage to using named branches is that every changeset on a
|
||
|
branch has the branch name as part of its metadata, which I find very helpful
|
||
|
(especially when using <a href="http://mercurial.selenic.com/wiki/GraphlogExtension">graphlog</a>).</p>
|
||
|
|
||
|
<h3 id="s12-disadvantages"><a href="index.html#s12-disadvantages">Disadvantages</a></h3>
|
||
|
|
||
|
<p>Many people don't like cluttering up changeset metadata with branch names,
|
||
|
especially if they're small branches that are going to be merged pretty
|
||
|
quickly.</p>
|
||
|
|
||
|
<p>In the past there was also the problem of not having a way to "close" a
|
||
|
branch, which means that over time the list of branches could get huge. This
|
||
|
was fixed in Mercurial 1.2 which introduced the <code>--close-branch</code> option for
|
||
|
<code>hg commit</code>.</p>
|
||
|
|
||
|
<h3 id="s13-comparison-to-git"><a href="index.html#s13-comparison-to-git">Comparison to git</a></h3>
|
||
|
|
||
|
<p>As far as I know git has no equivalent to Mercurial's named branches. Branch
|
||
|
information is never stored as part of a git changeset's metadata.</p>
|
||
|
|
||
|
<h2 id="s14-branching-anonymously"><a href="index.html#s14-branching-anonymously">Branching Anonymously</a></h2>
|
||
|
|
||
|
<p>The last method of branching with Mercurial is the fastest and easiest: update
|
||
|
to any revision you want and commit. You don't have to think up a name for it
|
||
|
or do anything else — just update and commit.</p>
|
||
|
|
||
|
<p>When you update to a specific revision, Mercurial will mark the parent of the
|
||
|
working directory as that changeset. When you commit, the newly created
|
||
|
changeset's parent will be the parent of the working directory.</p>
|
||
|
|
||
|
<p>The result of updating and committing without doing anything else would be:</p>
|
||
|
|
||
|
<p><img class="diagram" src="../../../../static/images/blog/2009/08/branch-anon.png" alt="Branching Anonymously"></p>
|
||
|
|
||
|
<p>How do you switch back and forth between branches once you do this? Just use
|
||
|
<code>hg update --check REV</code> with the revision number (or hash) (you can shorten
|
||
|
<code>--check</code> to <code>-c</code>).</p>
|
||
|
|
||
|
<p><strong>Note:</strong> the <code>--check</code> option was added in Mercurial 1.3, but it was broken.
|
||
|
It's fixed in 1.3.1. If you're using something earlier than 1.3.1, you really
|
||
|
should update.</p>
|
||
|
|
||
|
<p>Logging commands like <code>hg log</code> and <code>hg graphlog</code> will show you all the
|
||
|
changesets in the repository, so there's no danger of "losing" changesets.</p>
|
||
|
|
||
|
<h3 id="s15-advantages"><a href="index.html#s15-advantages">Advantages</a></h3>
|
||
|
|
||
|
<p>This is the fastest, easiest way to branch. You don't have to think of a name
|
||
|
or close/delete anything when you're finished — just update and commit.</p>
|
||
|
|
||
|
<p>This method is <em>great</em> for quick-fix, two-or-three-changeset branches.</p>
|
||
|
|
||
|
<h3 id="s16-disadvantages"><a href="index.html#s16-disadvantages">Disadvantages</a></h3>
|
||
|
|
||
|
<p>Using anonymous branching obviously means that there won't be any descriptive
|
||
|
name for a branch, so you'll need to write good commit messages if you want to
|
||
|
remember what a branch was for a couple of months later.</p>
|
||
|
|
||
|
<p>Not having a single name to represent a branch means that you'll need to look
|
||
|
up the revision numbers or hashes with <code>hg log</code> or <code>hg graphlog</code> each time you
|
||
|
want to switch back and forth. If you're switching a lot this might be more
|
||
|
trouble than it's worth.</p>
|
||
|
|
||
|
<h3 id="s17-comparison-to-git"><a href="index.html#s17-comparison-to-git">Comparison to git</a></h3>
|
||
|
|
||
|
<p>Git has no real way to handle this. Sure, it lets you update and commit, but
|
||
|
if you don't create a (named) ref to that new commit you're never going to
|
||
|
find it again once you switch to another one. Well, unless you feel like
|
||
|
grep'ing through a bunch of log output.</p>
|
||
|
|
||
|
<p>Oh, and hopefully it doesn't get garbage collected.</p>
|
||
|
|
||
|
<p>Sometimes you might not want to think up a name for a quick-fix branch. With
|
||
|
git you <em>have</em> to name it if you want to really do anything with it, with
|
||
|
Mercurial you don't.</p>
|
||
|
|
||
|
<h2 id="s18-one-more-difference-between-mercurial-and-git"><a href="index.html#s18-one-more-difference-between-mercurial-and-git">One More Difference Between Mercurial and git</a></h2>
|
||
|
|
||
|
<p>There's one more <em>big</em> difference between Mercurial's branching and git's
|
||
|
branching:</p>
|
||
|
|
||
|
<p><strong>Mercurial will push/pull <em>all</em> branches by default, while git will push/pull
|
||
|
only the <em>current</em> branch.</strong></p>
|
||
|
|
||
|
<p>This is important if you're a git user working with Mercurial. If you want to
|
||
|
push/pull only a single branch with Mercurial you can use the <code>--rev</code> option
|
||
|
(<code>-r</code> for short) and specify the tip revision of the branch:</p>
|
||
|
|
||
|
<pre><code>$ hg push --rev branchname
|
||
|
$ hg push --rev bookmarkname
|
||
|
$ hg push --rev 4</code></pre>
|
||
|
|
||
|
<p>If you specify a revision, Mercurial will push that changeset and any
|
||
|
ancestors of it that the target doesn't already have.</p>
|
||
|
|
||
|
<p>This doesn't apply when you use the "Branching with Clones" method because the
|
||
|
branches are separate repositories.</p>
|
||
|
|
||
|
<h2 id="s19-conclusion"><a href="index.html#s19-conclusion">Conclusion</a></h2>
|
||
|
|
||
|
<p>I hope this guide is helpful. If you see anything I've missed, especially on
|
||
|
the git side of things (I don't use git any more than I have to) or have any
|
||
|
questions please let me know!</p>
|
||
|
</article></main><hr class='main-separator' /><footer><nav><a href='https://github.com/sjl/'>GitHub</a> ・ <a href='https://twitter.com/stevelosh/'>Twitter</a> ・ <a href='https://instagram.com/thirtytwobirds/'>Instagram</a> ・ <a href='https://hg.stevelosh.com/.plan/'>.plan</a></nav></footer></body></html>
|