version control cheatsheet
· 1 year ago
facf65873ecb453513012bb41799040ff4d257e3
Parent:
7f90d029f
1 file changed +868 −0
- versioncontrol.html +868 −0
Diff
--- /dev/null +++ b/versioncontrol.html @@ -0,0 +1,868 @@ +<!DOCTYPE html> +<html lang="en"> +<head> + <meta charset="UTF-8"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> + <title>Modern Source Control Cheatsheet - Git, Mercurial, GitHub, GitLab, Bitbucket, Azure DevOps</title> + + <!-- SEO Meta Description --> + <meta name="description" content="Interactive cheatsheet comparing modern source control systems (Git, Mercurial) and hosting platforms (GitHub, GitLab, Bitbucket, Azure DevOps) covering concepts, workflows, features, and tradeoffs."> + + <!-- Canonical URL (Update if hosted) --> + <link rel="canonical" href="http://your-domain.com/source-control-cheatsheet.html"> + + <!-- Social Media Metadata --> + <!-- Open Graph / Facebook --> + <meta property="og:title" content="Modern Source Control Cheatsheet - Systems & Platforms"> + <meta property="og:description" content="Interactive visual guide comparing Git, Mercurial, GitHub, GitLab, Bitbucket, Azure DevOps on core concepts, workflows, features & use cases."> + <meta property="og:type" content="article"> + <meta property="og:url" content="http://your-domain.com/source-control-cheatsheet.html"> + <!-- <meta property="og:image" content="http://your-domain.com/images/source-control.png"> --> + <!-- <meta property="og:image:alt" content="Diagram showing connections between source control concepts, systems like Git, and platforms like GitHub."> --> + + <!-- Twitter Card --> + <meta name="twitter:card" content="summary_large_image"> + <meta name="twitter:title" content="Modern Source Control Cheatsheet - Systems & Platforms"> + <meta name="twitter:description" content="Interactive visual guide comparing Git, Mercurial, GitHub, GitLab, Bitbucket, Azure DevOps on core concepts, workflows, features & use cases."> + <!-- <meta name="twitter:image" content="http://your-domain.com/images/source-control.png"> --> + <!-- <meta name="twitter:image:alt" content="Diagram showing connections between source control concepts, systems like Git, and platforms like GitHub."> --> + + <!-- Favicon links (optional but recommended) --> + <!-- <link rel="icon" href="/favicon.ico" sizes="any"> --> + <!-- <link rel="icon" href="/favicon.svg" type="image/svg+xml"> --> + <!-- <link rel="apple-touch-icon" href="/apple-touch-icon.png"> --> + + <link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet"> + <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/font/bootstrap-icons.min.css"> + + <style> + :root { + --bs-body-bg: #e9eef2; /* Light blue-gray background */ + --bs-primary: #0d6efd; /* Standard Bootstrap Blue */ + --bs-primary-dark: #0a58ca; + --bs-primary-light: #cfe2ff; + --card-border-color: #adb5bd; /* Lighter gray border */ + --card-shadow-color: rgba(0, 40, 100, .1); + --text-color-main: #212529; /* Darker text */ + --text-color-secondary: #495057; /* Medium gray text */ + --text-color-highlight: var(--bs-primary-dark); + --blueprint-grid-color: rgba(173, 181, 189, 0.15); /* Subtle grid */ + --schema-bg-color: rgba(255, 255, 255, 0.7); /* Slightly more opaque white */ + --schema-border-color: #dee2e6; /* Standard Bootstrap border */ + + /* --- Category Colors --- */ + --sc-color-concept: #6c757d; /* Gray */ + --sc-color-git: #f05033; /* Git Orange/Red */ + --sc-color-mercurial: #93cde8; /* Mercurial Blue */ + --sc-color-platform: #6f42c1; /* Purple */ + --sc-color-workflow: #fd7e14; /* Orange */ + --sc-color-choosing: #0d6efd; /* Bootstrap Blue */ + + --sc-category-color: var(--sc-color-concept); /* Default */ + } + + @keyframes blueprintGridAnimation { + 0% { background-position: 0 0, 0 0; } + 100% { background-position: 50px 50px, -50px -50px; } + } + + body { + background-color: var(--bs-body-bg); + background-image: + linear-gradient(to right, var(--blueprint-grid-color) 1px, transparent 1px), + linear-gradient(to bottom, var(--blueprint-grid-color) 1px, transparent 1px); + background-size: 50px 50px; + animation: blueprintGridAnimation 75s linear infinite; + font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; + padding-bottom: 3rem; + font-size: 16px; + color: var(--text-color-main); + box-sizing: border-box; + } + *, *::before, *::after { box-sizing: inherit; } + + .page-header { + background: linear-gradient(135deg, #f8f9fa, #e9ecef); /* Lighter gradient */ + padding: 2.5rem 1.5rem; + text-align: center; + border-bottom: 2px solid var(--schema-border-color); + margin-bottom: 3rem; + position: relative; + z-index: 10; + box-shadow: 0 4px 15px rgba(0, 0, 0, 0.05); /* Subtler shadow */ + } + .page-header h1 { + color: #343a40; /* Darker heading */ + font-weight: 300; /* Lighter weight */ + letter-spacing: 0.5px; + margin-bottom: 0.5rem; + font-size: 2.8rem; + } + .page-header h1 .bi { font-size: 0.9em; vertical-align: -0.05em; margin-right: 0.3em; color: var(--bs-primary); } + .page-header .lead { color: #495057; font-size: 1.15rem; max-width: 800px; margin: auto; } + + .schema-container { + background-color: var(--schema-bg-color); + border: 1px solid var(--schema-border-color); /* Thinner border */ + border-radius: 8px; + padding: 1.5rem 1.5rem 0.5rem 1.5rem; + margin-bottom: 2.5rem; + box-shadow: 0 3px 10px rgba(0, 0, 0, 0.05); /* Subtler shadow */ + backdrop-filter: blur(3px); + position: relative; + transition: opacity 0.3s ease-in-out; + } + + .section-title { + color: var(--sc-category-color); + margin: -2.8rem 0 1.5rem 0; + font-weight: 600; + text-transform: uppercase; + letter-spacing: .08em; + font-size: 1.1rem; + border-bottom: none; + padding: 0.4rem 1rem; + background-color: var(--bs-body-bg); + display: inline-block; + position: relative; + left: 1rem; + z-index: 15; + border: 1px solid var(--schema-border-color); + border-bottom: none; + border-radius: 6px 6px 0 0; + transition: opacity 0.3s ease-in-out; + } + + /* --- Card Styling --- */ + .info-card { + background: #fff; + border: 1px solid var(--card-border-color); + border-radius: 4px; /* Slightly more rounded */ + box-shadow: 0 2px 5px var(--card-shadow-color); + height: 100%; + display: flex; + flex-direction: column; + transition: box-shadow 0.3s ease, opacity 0.3s ease; + position: relative; + z-index: 5; + opacity: 1; + } + + /* --- Dimming Logic --- */ + #main-container.is-dimmed .schema-container:not(.is-highlighted-section) .info-card { + opacity: 0.4; + } + #main-container.is-dimmed .schema-container:not(.is-highlighted-section) > .section-title { + opacity: 0.5; + } + + /* Highlight style */ + .info-card.is-highlighted { + opacity: 1 !important; + box-shadow: 0 0 0 3px var(--sc-category-color), 0 4px 10px rgba(0, 0, 0, .1) !important; + z-index: 25 !important; + } + + /* Subtle hover effect when NOT highlighted */ + .info-card:not(.is-highlighted):hover { + box-shadow: 0 4px 10px rgba(0, 0, 0, .1); + z-index: 20; + } + + .info-card .card-body { padding: 0; flex-grow: 1; display: flex; flex-direction: column; } + .info-card h5 { + color: #fff; background-color: var(--sc-category-color); + font-size: 1rem; text-align: center; margin: 0; padding: 0.6rem 0.5rem; + font-weight: 600; display: flex; justify-content: center; align-items: center; + gap: .5rem; font-family: Consolas, Menlo, Monaco, 'Courier New', monospace; + border-bottom: 1px solid var(--card-border-color); + border-radius: 3px 3px 0 0; /* Match card radius */ + } + .info-card h5 .bi { font-size: 1.2em; color: #fff; opacity: 0.9; } + .card-content-wrapper { padding: 1rem; flex-grow: 1; display: flex; flex-direction: column; } + .info-card p.summary { font-size: .9rem; color: var(--text-color-secondary); margin-bottom: .8rem; flex-grow: 1; } + + /* Attribute List Styling */ + .collapse-content { font-size: 0.9rem; border-top: 1px solid #e9ecef; padding: 1rem; margin-top: 1rem; color: var(--text-color-main); } + .collapse-content h6 { font-weight: 700; color: var(--text-color-highlight); margin-top: 0.8rem; margin-bottom: 0.3rem; font-size: 0.95rem; } + .collapse-content ul { padding-left: 0.5rem; margin-bottom: 0.8rem; list-style: none; } + .collapse-content li { margin-bottom: 0.6rem; padding-bottom: 0.6rem; font-size: 0.88rem; line-height: 1.5; border-bottom: 1px dotted #dee2e6; position: relative; padding-left: 1.5rem; } + .collapse-content li:last-child { border-bottom: none; margin-bottom: 0; } + .collapse-content li::before { content: "\F288"; /* Bootstrap Icons code - checkmark */ font-family: "bootstrap-icons"; position: absolute; left: 0; top: 2px; color: var(--sc-category-color); opacity: 0.7; font-size: 0.9em; } + .collapse-content li strong { color: var(--text-color-highlight); display: block; margin-bottom: 0.2rem; font-weight: 600; } + .collapse-content p { font-size: 0.9rem; margin-bottom: 0.6rem; line-height: 1.55; } + .collapse-content code { font-size: 0.85rem; color: #d63384; /* Bootstrap pink */ background-color: #f8f9fa; padding: 0.1em 0.4em; border-radius: 3px; font-family: Consolas, Menlo, Monaco, 'Courier New', monospace; } + + .row > * { margin-bottom: 2rem; } /* Restore bottom margin for multi-card rows */ + footer { padding-top: 3rem; font-size: .85em; color: #6c757d; position: relative; z-index: 10; text-align: center; } + + .details-toggle { + font-size: 0.8rem; margin-top: auto; align-self: flex-start; + padding: 0.3rem 0.6rem; color: var(--sc-category-color); + border: 1px solid var(--sc-category-color); background-color: transparent; + transition: background-color 0.2s ease, color 0.2s ease; + border-radius: 3px; + } + .details-toggle:hover { background-color: var(--sc-category-color); color: white; } + .details-toggle .bi { transition: transform 0.2s ease-in-out; } + .details-toggle[aria-expanded="true"] .bi { transform: rotate(180deg); } + + .term { font-weight: 600; color: var(--bs-primary-dark); background-color: var(--bs-primary-light); padding: 0.1em 0.3em; border-radius: 3px;} + + /* Color Coding Class Assignments */ + .cat-concept { --sc-category-color: var(--sc-color-concept); } + .cat-dvcs .vcs-git { --sc-category-color: var(--sc-color-git); } + .cat-dvcs .vcs-mercurial { --sc-category-color: var(--sc-color-mercurial); } + .cat-platform { --sc-category-color: var(--sc-color-platform); } + .cat-workflow { --sc-category-color: var(--sc-color-workflow); } + .cat-choosing { --sc-category-color: var(--sc-color-choosing); } + + /* Default color for DVCS section if needed */ + .cat-dvcs { --sc-category-color: var(--sc-color-git); } /* Default to Git color */ + + </style> +</head> +<body> +<header class="page-header"> + <h1 class="display-5"><i class="bi bi-git"></i> Modern Source Control</h1> + <p class="lead">An interactive guide to modern Version Control Systems (VCS), concepts, platforms, and workflows.</p> +</header> +<div class="container" id="main-container"> + + <!-- 1. FOUNDATIONAL CONCEPTS --> + <div class="schema-container cat-concept" data-section-id="section-concepts"> + <h2 class="section-title" id="section-concepts">Foundational Concepts</h2> + <div class="row"> + <div class="col-lg-4 col-md-6"> + <div class="info-card" id="card-dvcs"> + <div class="card-body"> + <h5><i class="bi bi-diagram-3"></i> DVCS Philosophy</h5> + <div class="card-content-wrapper"> + <p class="summary"><span class="term">Distributed Version Control Systems</span> (DVCS) like Git & Mercurial give every developer a <span class="term">full repository copy</span>, enabling offline work, faster operations, and flexible workflows.</p> + <button class="btn btn-sm details-toggle" type="button" data-bs-toggle="collapse" data-bs-target="#collapseConcept1" aria-expanded="false" aria-controls="collapseConcept1"> + Details <i class="bi bi-chevron-down"></i> + </button> + </div> + </div> + <div class="collapse collapse-content" id="collapseConcept1"> + <h6>Core Idea</h6> + <p>Unlike older Centralized VCS (like SVN or CVS) where developers checked out files from a single central server, DVCS provides each user with a complete, independent copy (clone) of the entire repository history.</p> + <h6>Key Advantages</h6> + <ul> + <li><strong>Offline Work:</strong> Commit, branch, view history, and merge without needing a network connection.</li> + <li><strong>Performance:</strong> Most operations (commit, branch, merge, diff) are local and thus significantly faster.</li> + <li><strong>Redundancy:</strong> Every clone is effectively a full backup of the repository.</li> + <li><strong>Workflow Flexibility:</strong> Enables complex branching strategies and collaboration models (e.g., pull requests).</li> + <li><strong>Collaboration:</strong> Easily share changes between any two repositories, not just client-server.</li> + </ul> + <h6>Shift from Centralized</h6> + <p>The move to DVCS addressed key limitations of CVCS, particularly around branching/merging complexity, performance bottlenecks, and reliance on network connectivity.</p> + </div> + </div> + </div> + <div class="col-lg-4 col-md-6"> + <div class="info-card" id="card-repository"> + <div class="card-body"> + <h5><i class="bi bi-archive"></i> Repository (Repo)</h5> + <div class="card-content-wrapper"> + <p class="summary">A collection of <span class="term">files</span> and the <span class="term">history</span> of their changes. In DVCS, you have a local copy and interact with remote copies (e.g., on GitHub).</p> + <button class="btn btn-sm details-toggle" type="button" data-bs-toggle="collapse" data-bs-target="#collapseConcept2" aria-expanded="false" aria-controls="collapseConcept2"> + Details <i class="bi bi-chevron-down"></i> + </button> + </div> + </div> + <div class="collapse collapse-content" id="collapseConcept2"> + <h6>What it Contains</h6> + <p>A repository stores all the files belonging to a project, plus the complete history of modifications made to those files over time. This history is typically stored as a series of <span class="term">commits</span>.</p> + <h6>Local vs. Remote</h6> + <ul> + <li><strong>Local Repository:</strong> The full copy residing on your own computer. This is where you do your work: edit files, commit changes, create branches.</li> + <li><strong>Remote Repository:</strong> A copy hosted on a server (e.g., GitHub, GitLab, a company server). Used for collaboration, backup, and sharing code with others. Common remote names include <code>origin</code>.</li> + </ul> + <h6>Operations</h6> + <p>You typically <span class="term">clone</span> a remote repository to create your local copy, <span class="term">pull</span> changes from a remote, and <span class="term">push</span> your local changes to a remote.</p> + </div> + </div> + </div> + <div class="col-lg-4 col-md-6"> + <div class="info-card" id="card-commit"> + <div class="card-body"> + <h5><i class="bi bi-check2-circle"></i> Commit</h5> + <div class="card-content-wrapper"> + <p class="summary">A <span class="term">snapshot</span> of your project's files at a specific point in time, saved to the repository's history. Each commit has a unique ID and a message.</p> + <button class="btn btn-sm details-toggle" type="button" data-bs-toggle="collapse" data-bs-target="#collapseConcept3" aria-expanded="false" aria-controls="collapseConcept3"> + Details <i class="bi bi-chevron-down"></i> + </button> + </div> + </div> + <div class="collapse collapse-content" id="collapseConcept3"> + <h6>Purpose</h6> + <p>Commits are the fundamental building blocks of a project's history. They represent saved states that you can reference, revert to, or compare against.</p> + <h6>Components</h6> + <ul> + <li><strong>Snapshot:</strong> Records the state of all tracked files at that moment. DVCS like Git often store this efficiently, only recording changes relative to previous commits.</li> + <li><strong>Metadata:</strong> Includes the author, committer, timestamp, and a unique identifier (e.g., SHA-1 hash in Git).</li> + <li><strong>Parent(s):</strong> Points to the preceding commit(s). A standard commit has one parent; a merge commit has two or more.</li> + <li><strong>Commit Message:</strong> A description written by the author explaining the changes made in the commit. Crucial for understanding history.</li> + </ul> + <h6>Workflow (Git Example)</h6> + <p>Typically, you modify files, <span class="term">stage</span> the specific changes you want to include (<code>git add</code>), and then <span class="term">commit</span> them with a message (<code>git commit</code>).</p> + </div> + </div> + </div> + <div class="col-lg-4 col-md-6"> + <div class="info-card" id="card-branch"> + <div class="card-body"> + <h5><i class="bi bi-diagram-2"></i> Branch</h5> + <div class="card-content-wrapper"> + <p class="summary">An <span class="term">independent line of development</span>. Branches allow you to work on features or fixes without affecting the main codebase (e.g., <code>main</code> or <code>master</code>).</p> + <button class="btn btn-sm details-toggle" type="button" data-bs-toggle="collapse" data-bs-target="#collapseConcept4" aria-expanded="false" aria-controls="collapseConcept4"> + Details <i class="bi bi-chevron-down"></i> + </button> + </div> + </div> + <div class="collapse collapse-content" id="collapseConcept4"> + <h6>Concept</h6> + <p>Think of a branch as a movable pointer to a specific commit. When you create a branch, you create a new pointer. As you make commits on that branch, the pointer moves forward.</p> + <h6>Why Use Branches?</h6> + <ul> + <li><strong>Isolation:</strong> Develop features, experiment, or fix bugs without destabilizing the main line of code.</li> + <li><strong>Parallel Development:</strong> Multiple team members can work on different features simultaneously on separate branches.</li> + <li><strong>Organization:</strong> Keep related changes grouped together (e.g., a 'feature/user-login' branch).</li> + <li><strong>Workflow Enablement:</strong> Basis for workflows like Gitflow or GitHub Flow, often involving Pull Requests.</li> + </ul> + <h6>Common Operations</h6> + <p>Creating a branch (<code>git branch feature-x</code>), switching to it (<code>git checkout feature-x</code> or <code>git switch feature-x</code>), making commits, and eventually merging it back.</p> + </div> + </div> + </div> + <div class="col-lg-4 col-md-6"> + <div class="info-card" id="card-merge"> + <div class="card-body"> + <h5><i class="bi bi-bezier2"></i> Merge</h5> + <div class="card-content-wrapper"> + <p class="summary">The process of <span class="term">combining changes</span> from different branches back into one. Resolves differences between the development histories.</p> + <button class="btn btn-sm details-toggle" type="button" data-bs-toggle="collapse" data-bs-target="#collapseConcept5" aria-expanded="false" aria-controls="collapseConcept5"> + Details <i class="bi bi-chevron-down"></i> + </button> + </div> + </div> + <div class="collapse collapse-content" id="collapseConcept5"> + <h6>Goal</h6> + <p>To integrate work done on a separate branch (e.g., a feature branch) into another branch (e.g., <code>main</code>).</p> + <h6>How it Works</h6> + <p>VCS tools analyze the histories of the branches being merged. </p> + <ul> + <li><strong>Fast-Forward Merge:</strong> If the target branch hasn't diverged (no new commits), the target branch pointer simply moves forward to the source branch's latest commit. Simple and clean history.</li> + <li><strong>Three-Way Merge:</strong> If both branches have diverged, the VCS finds a common ancestor commit and combines the changes from both branches since that ancestor. This typically creates a new <span class="term">merge commit</span> with two parents.</li> + </ul> + <h6>Merge Conflicts</h6> + <p>Occur when both branches modified the same part of the same file differently. The VCS cannot automatically decide which change to keep, requiring manual intervention by the developer to resolve the conflict before completing the merge.</p> + <h6>Alternatives</h6> + <p><span class="term">Rebasing</span> (e.g., <code>git rebase</code>) is another way to integrate changes, rewriting history to make it appear linear. Has different tradeoffs regarding history clarity and collaboration.</p> + </div> + </div> + </div> + </div> <!-- /.row --> + </div> <!-- /.schema-container --> + + <!-- 2. DISTRIBUTED VERSION CONTROL SYSTEMS --> + <div class="schema-container cat-dvcs" data-section-id="section-dvcs"> + <h2 class="section-title" id="section-dvcs">Distributed Version Control Systems</h2> + <div class="row"> + <div class="col-lg-6"> + <div class="info-card vcs-git" id="card-git"> + <div class="card-body"> + <h5><i class="bi bi-git"></i> Git</h5> + <div class="card-content-wrapper"> + <p class="summary">The <span class="term">dominant DVCS</span>, known for speed, flexibility, powerful branching/merging, and a vast ecosystem. Features a <span class="term">staging area</span>.</p> + <button class="btn btn-sm details-toggle" type="button" data-bs-toggle="collapse" data-bs-target="#collapseGit" aria-expanded="false" aria-controls="collapseGit"> + Details <i class="bi bi-chevron-down"></i> + </button> + </div> + </div> + <div class="collapse collapse-content" id="collapseGit"> + <h6>Philosophy & Core</h6> + <p>Designed by Linus Torvalds for Linux kernel development. Focuses on performance, data integrity (content-addressable storage using SHA-1), and support for non-linear workflows (branching).</p> + <h6>Key Features</h6> + <ul> + <li><strong>Staging Area (Index):</strong> Intermediate step between working directory and repository history. Allows crafting precise commits.</li> + <li><strong>Branching Model:</strong> Extremely lightweight and fast branching and merging.</li> + <li><strong>Distributed Nature:</strong> Full repository locally, facilitating offline work and peer-to-peer sharing.</li> + <li><strong>Performance:</strong> Most operations are very fast as they are local.</li> + <li><strong>Flexibility:</strong> Supports diverse workflows (Gitflow, GitHub Flow, etc.). Commands like <code>rebase</code> allow history manipulation (use with care).</li> + </ul> + <h6>Common Commands</h6> + <p><code>git clone</code>, <code>git add</code>, <code>git commit</code>, <code>git status</code>, <code>git log</code>, <code>git branch</code>, <code>git checkout</code>/<code>git switch</code>, <code>git merge</code>, <code>git pull</code>, <code>git push</code>, <code>git fetch</code>, <code>git rebase</code>.</p> + <h6>Strengths</h6> + <ul> + <li>Industry standard, huge community, extensive tooling and platform support (GitHub, GitLab, etc.).</li> + <li>Excellent performance for most operations.</li> + <li>Powerful and flexible branching/merging capabilities.</li> + <li>Staging area allows granular control over commits.</li> + </ul> + <h6>Tradeoffs</h6> + <ul> + <li>Can have a steeper learning curve compared to Mercurial initially (especially concepts like the staging area, reset, rebase).</li> + <li>Command-line interface can feel complex with many options.</li> + <li>Handling very large binary files can require extensions (Git LFS).</li> + </ul> + <h6>Use Cases</h6> + <p>Software development of all sizes, open-source projects, infrastructure as code, documentation, anywhere collaborative text-based file tracking is needed.</p> + </div> + </div> + </div> + <div class="col-lg-6"> + <div class="info-card vcs-mercurial" id="card-mercurial"> + <div class="card-body"> + <h5><i class="bi bi-infinity"></i> Mercurial (Hg)</h5> + <div class="card-content-wrapper"> + <p class="summary">A DVCS focused on <span class="term">simplicity</span>, ease of use, and performance. Often considered more intuitive than Git initially.</p> + <button class="btn btn-sm details-toggle" type="button" data-bs-toggle="collapse" data-bs-target="#collapseHg" aria-expanded="false" aria-controls="collapseHg"> + Details <i class="bi bi-chevron-down"></i> + </button> + </div> + </div> + <div class="collapse collapse-content" id="collapseHg"> + <h6>Philosophy & Core</h6> + <p>Designed with user-friendliness and consistency in mind. Aims to provide powerful DVCS features with a simpler command set and conceptual model compared to Git.</p> + <h6>Key Features</h6> + <ul> + <li><strong>Simpler Interface:</strong> Commands are often seen as more consistent and intuitive. No direct equivalent of Git's staging area by default (commits typically include all tracked changes).</li> + <li><strong>Branching Concepts:</strong> Supports multiple ways to handle branches (named branches, bookmarks, anonymous heads), which can be confusing but offers flexibility. Named branches are permanent markers in history.</li> + <li><strong>Extensibility:</strong> Features can be added via extensions (e.g., rebase, largefiles support similar to Git LFS).</li> + <li><strong>Performance:</strong> Generally excellent performance, competitive with Git.</li> + <li><strong>Windows Support:</strong> Historically known for strong native Windows support.</li> + </ul> + <h6>Common Commands</h6> + <p><code>hg clone</code>, <code>hg add</code>, <code>hg commit</code> (or <code>hg ci</code>), <code>hg status</code>, <code>hg log</code>, <code>hg branch</code>, <code>hg update</code> (switches branches/commits), <code>hg merge</code>, <code>hg pull</code>, <code>hg push</code>, <code>hg heads</code>.</p> + <h6>Strengths</h6> + <ul> + <li>Easier initial learning curve for many users.</li> + <li>Consistent command-line interface.</li> + <li>Good performance.</li> + <li>Built-in web interface (<code>hg serve</code>).</li> + </ul> + <h6>Tradeoffs</h6> + <ul> + <li>Smaller community and ecosystem compared to Git.</li> + <li>Less prevalent on major hosting platforms (though Bitbucket has excellent support).</li> + <li>Branching model (especially named branches vs bookmarks) can be confusing.</li> + <li>Some advanced operations require enabling extensions.</li> + </ul> + <h6>Use Cases</h6> + <p>Software development (especially where ease of use is prioritized), large projects (used by Facebook/Meta internally), teams comfortable with its branching models.</p> + </div> + </div> + </div> + </div> <!-- /.row --> + </div> <!-- /.schema-container --> + + <!-- 3. SOURCE CODE HOSTING PLATFORMS --> + <div class="schema-container cat-platform" data-section-id="section-platforms"> + <h2 class="section-title" id="section-platforms">Source Code Hosting Platforms</h2> + <div class="row"> + <div class="col-lg-3 col-md-6"> + <div class="info-card" id="card-github"> + <div class="card-body"> + <h5><i class="bi bi-github"></i> GitHub</h5> + <div class="card-content-wrapper"> + <p class="summary">The most popular platform for hosting Git repositories. Strong focus on <span class="term">collaboration</span>, <span class="term">open source</span>, and developer community features.</p> + <button class="btn btn-sm details-toggle" type="button" data-bs-toggle="collapse" data-bs-target="#collapsePlatform1" aria-expanded="false" aria-controls="collapsePlatform1"> + Details <i class="bi bi-chevron-down"></i> + </button> + </div> + </div> + <div class="collapse collapse-content" id="collapsePlatform1"> + <h6>Core Offerings</h6> + <p>Git repository hosting, Pull Requests (code review/merge workflow), issue tracking, project management (Projects), CI/CD (GitHub Actions), package hosting (Packages), wikis, security scanning (Dependabot, Code Scanning), large community.</p> + <h6>Key Features</h6> + <ul> + <li><strong>Pull Requests:</strong> Core collaborative code review and merging mechanism.</li> + <li><strong>GitHub Actions:</strong> Powerful, integrated CI/CD and workflow automation platform.</li> + <li><strong>Community Focus:</strong> Hub for open-source projects, social coding features (following, starring).</li> + <li><strong>Marketplace:</strong> Integrations with numerous third-party developer tools.</li> + <li><strong>Codespaces:</strong> Cloud-based development environments.</li> + <li><strong>Copilot:</strong> AI pair programmer integration.</li> + </ul> + <h6>Strengths</h6> + <ul> + <li>Massive user base and community effect.</li> + <li>Excellent UI/UX, generally intuitive.</li> + <li>Powerful and flexible GitHub Actions.</li> + <li>Generous free tier for public and private repositories.</li> + <li>Strong focus on security features.</li> + </ul> + <h6>Tradeoffs</h6> + <ul> + <li>Owned by Microsoft (a concern for some).</li> + <li>CI/CD minutes/storage limits on free/lower tiers can be restrictive for large projects.</li> + <li>Project management features less mature than specialized tools like Jira.</li> + </ul> + </div> + </div> + </div> + <div class="col-lg-3 col-md-6"> + <div class="info-card" id="card-gitlab"> + <div class="card-body"> + <h5><i class="bi bi-gitlab"></i> GitLab</h5> + <div class="card-content-wrapper"> + <p class="summary">An <span class="term">integrated DevOps platform</span> built around Git hosting. Offers a complete toolchain from planning to monitoring. <span class="term">Self-hosting</span> option available.</p> + <button class="btn btn-sm details-toggle" type="button" data-bs-toggle="collapse" data-bs-target="#collapsePlatform2" aria-expanded="false" aria-controls="collapsePlatform2"> + Details <i class="bi bi-chevron-down"></i> + </button> + </div> + </div> + <div class="collapse collapse-content" id="collapsePlatform2"> + <h6>Core Offerings</h6> + <p>Git repository hosting, Merge Requests, issue tracking with boards, powerful integrated CI/CD (GitLab CI/CD), container registry, security scanning (SAST, DAST, etc.), monitoring, planning tools (Epics, Roadmaps), wiki.</p> + <h6>Key Features</h6> + <ul> + <li><strong>Single Application:</strong> Aims to provide the entire DevOps lifecycle in one platform.</li> + <li><strong>GitLab CI/CD:</strong> Highly integrated, powerful, and configurable CI/CD using a <code>.gitlab-ci.yml</code> file.</li> + <li><strong>Self-Managed Option:</strong> Can be installed on your own infrastructure (Community Edition is open source).</li> + <li><strong>Security Focus:</strong> Comprehensive suite of security scanning tools integrated into the development workflow (DevSecOps).</li> + <li><strong>Auto DevOps:</strong> Opinionated pipeline for automating build, test, deploy, and monitoring.</li> + </ul> + <h6>Strengths</h6> + <ul> + <li>All-in-one DevOps platform reduces toolchain complexity.</li> + <li>Mature and powerful built-in CI/CD.</li> + <li>Strong security features integrated throughout.</li> + <li>Viable self-hosting option with the open-source Community Edition.</li> + <li>Transparent development process.</li> + </ul> + <h6>Tradeoffs</h6> + <ul> + <li>Can feel complex due to the sheer number of features.</li> + <li>UI can sometimes be less polished or intuitive than GitHub.</li> + <li>Free tier CI/CD limits can be hit quickly.</li> + <li>Self-hosting requires operational overhead.</li> + </ul> + </div> + </div> + </div> + <div class="col-lg-3 col-md-6"> + <div class="info-card" id="card-bitbucket"> + <div class="card-body"> + <h5><i class="bi bi-bitbucket"></i> Bitbucket Cloud</h5> + <div class="card-content-wrapper"> + <p class="summary">Atlassian's Git (and historically Mercurial) hosting platform. Known for excellent <span class="term">integration</span> with other Atlassian tools like <span class="term">Jira and Trello</span>.</p> + <button class="btn btn-sm details-toggle" type="button" data-bs-toggle="collapse" data-bs-target="#collapsePlatform3" aria-expanded="false" aria-controls="collapsePlatform3"> + Details <i class="bi bi-chevron-down"></i> + </button> + </div> + </div> + <div class="collapse collapse-content" id="collapsePlatform3"> + <h6>Core Offerings</h6> + <p>Git repository hosting (Mercurial support deprecated for new repos), Pull Requests, integrated CI/CD (Bitbucket Pipelines), code search, issue tracking integration (Jira), project tracking integration (Trello).</p> + <h6>Key Features</h6> + <ul> + <li><strong>Atlassian Ecosystem Integration:</strong> Seamless workflow between Bitbucket, Jira (issue tracking), Trello (boards), Confluence (documentation), etc.</li> + <li><strong>Bitbucket Pipelines:</strong> Integrated CI/CD configured within the repository (<code>bitbucket-pipelines.yml</code>).</li> + <li><strong>Code Insights:</strong> Surface information from scanning/testing tools directly in Pull Requests.</li> + <li><strong>Free Tier:</strong> Offers free private repositories for small teams (up to 5 users).</li> + </ul> + <h6>Strengths</h6> + <ul> + <li>Unbeatable integration if you're heavily invested in the Atlassian suite (Jira especially).</li> + <li>Competitive pricing, potentially cheaper for small teams needing private repos than GitHub historically.</li> + <li>Simple and effective built-in CI/CD with Pipelines.</li> + <li>Clean UI.</li> + </ul> + <h6>Tradeoffs</h6> + <ul> + <li>Smaller community compared to GitHub.</li> + <li>CI/CD (Pipelines) may be less flexible or powerful than GitHub Actions or GitLab CI for complex scenarios.</li> + <li>Less focus on open-source community features.</li> + <li>Mercurial support is effectively legacy.</li> + </ul> + <h6>Use Cases</h6> + <p>Teams using Jira for project management, organizations standardized on Atlassian tools, small teams needing cost-effective private repositories.</p> + </div> + </div> + </div> + <div class="col-lg-3 col-md-6"> + <div class="info-card" id="card-azure-devops"> + <div class="card-body"> + <h5><i class="bi bi-microsoft"></i> Azure DevOps Repos</h5> + <div class="card-content-wrapper"> + <p class="summary">Microsoft's Git hosting service within the broader <span class="term">Azure DevOps</span> suite. Strong integration with Azure cloud and other DevOps services.</p> + <button class="btn btn-sm details-toggle" type="button" data-bs-toggle="collapse" data-bs-target="#collapsePlatform4" aria-expanded="false" aria-controls="collapsePlatform4"> + Details <i class="bi bi-chevron-down"></i> + </button> + </div> + </div> + <div class="collapse collapse-content" id="collapsePlatform4"> + <h6>Core Offerings</h6> + <p>Part of Azure DevOps Services which includes: Azure Repos (Git hosting, TFVC also supported), Azure Pipelines (CI/CD), Azure Boards (Agile planning, work item tracking), Azure Test Plans, Azure Artifacts (package management).</p> + <h6>Key Features</h6> + <ul> + <li><strong>Integrated Suite:</strong> Provides tools across the development lifecycle, similar to GitLab but within the Microsoft Azure ecosystem.</li> + <li><strong>Azure Pipelines:</strong> Very powerful and flexible CI/CD system, supports building/deploying anywhere (not just Azure). YAML or classic visual editor.</li> + <li><strong>Azure Boards:</strong> Mature Agile planning and work tracking tools.</li> + <li><strong>Enterprise Focus:</strong> Strong support for permissions, policies, auditing, and integration with Azure Active Directory.</li> + <li><strong>TFVC Support:</strong> Also supports Microsoft's legacy centralized VCS (Team Foundation Version Control).</li> + </ul> + <h6>Strengths</h6> + <ul> + <li>Excellent integration with Azure cloud services.</li> + <li>Mature and powerful CI/CD (Azure Pipelines).</li> + <li>Comprehensive work tracking features (Azure Boards).</li> + <li>Strong enterprise governance and security features.</li> + <li>Generous free tier for small teams and open source projects.</li> + </ul> + <h6>Tradeoffs</h6> + <ul> + <li>UI can feel complex and sometimes dated compared to GitHub/GitLab.</li> + <li>Less prominent in the open-source community than GitHub.</li> + <li>Can feel heavily tied to the Microsoft ecosystem (though Pipelines can deploy anywhere).</li> + <li>Split between different services (Repos, Pipelines, Boards) can feel less unified than GitLab's approach.</li> + </ul> + <h6>Use Cases</h6> + <p>Organizations heavily invested in Microsoft Azure, enterprise teams needing strong governance and planning tools, teams using TFVC, projects requiring complex CI/CD pipelines.</p> + </div> + </div> + </div> + </div> <!-- /.row --> + </div> <!-- /.schema-container --> + + <!-- 4. KEY WORKFLOWS & CONCEPTS --> + <div class="schema-container cat-workflow" data-section-id="section-workflows"> + <h2 class="section-title" id="section-workflows">Key Workflows & Concepts</h2> + <div class="row"> + <div class="col-lg-4 col-md-6"> + <div class="info-card" id="card-workflow-branching"> + <div class="card-body"> + <h5><i class="bi bi-diagram-3-fill"></i> Branching Strategies</h5> + <div class="card-content-wrapper"> + <p class="summary">Defined patterns for using branches to manage development, releases, and fixes. Examples: <span class="term">Gitflow</span>, <span class="term">GitHub Flow</span>, <span class="term">GitLab Flow</span>.</p> + <button class="btn btn-sm details-toggle" type="button" data-bs-toggle="collapse" data-bs-target="#collapseWorkflow1" aria-expanded="false" aria-controls="collapseWorkflow1"> + Explore <i class="bi bi-chevron-down"></i> + </button> + </div> + </div> + <div class="collapse collapse-content" id="collapseWorkflow1"> + <p>Choosing a branching strategy standardizes how a team uses branches, improving coordination and predictability.</p> + <h6>Common Strategies</h6> + <ul> + <li><strong>Gitflow:</strong> A more complex model with dedicated branches for features (<code>feature/*</code>), releases (<code>release/*</code>), hotfixes (<code>hotfix/*</code>), development (<code>develop</code>), and production (<code>main</code>/<code>master</code>). Good for projects with scheduled releases.</li> + <li><strong>GitHub Flow:</strong> Simpler model. <code>main</code> is always deployable. New work is done on feature branches created from <code>main</code>. Changes are merged back into <code>main</code> via Pull Request and deployed immediately. Optimized for continuous delivery.</li> + <li><strong>GitLab Flow:</strong> Similar to GitHub Flow but adds optional environment branches (e.g., <code>production</code>, <code>staging</code>) or release branches, providing more flexibility between continuous delivery and versioned releases.</li> + <li><strong>Trunk-Based Development:</strong> Developers work in short-lived branches or commit directly to the main line (<code>trunk</code>/<code>main</code>), relying heavily on feature flags and automated testing. Requires mature CI/CD practices.</li> + </ul> + <p>The best strategy depends on team size, release cadence, deployment practices, and tooling.</p> + </div> + </div> + </div> + <div class="col-lg-4 col-md-6"> + <div class="info-card" id="card-workflow-pr"> + <div class="card-body"> + <h5><i class="bi bi-git"></i> Pull/Merge Requests</h5> + <div class="card-content-wrapper"> + <p class="summary">A mechanism on hosting platforms to propose changes from a branch, facilitating <span class="term">code review</span>, discussion, automated checks, and <span class="term">controlled merging</span>.</p> + <button class="btn btn-sm details-toggle" type="button" data-bs-toggle="collapse" data-bs-target="#collapseWorkflow2" aria-expanded="false" aria-controls="collapseWorkflow2"> + Explore <i class="bi bi-chevron-down"></i> + </button> + </div> + </div> + <div class="collapse collapse-content" id="collapseWorkflow2"> + <p>Pull Requests (GitHub, Bitbucket) or Merge Requests (GitLab, Azure DevOps) are central to modern collaborative workflows.</p> + <h6>Process Overview</h6> + <ol> + <li>Developer creates a feature branch, makes commits, and pushes it to the platform.</li> + <li>Developer opens a Pull/Merge Request (PR/MR) targeting the main branch (e.g., <code>main</code>).</li> + <li>Team members review the code changes, leave comments, and request modifications.</li> + <li>Automated checks (CI builds, tests, linters, security scans) run against the proposed changes.</li> + <li>Once approved and checks pass, the changes are merged into the target branch (often directly via the platform's UI).</li> + </ol> + <h6>Benefits</h6> + <ul> + <li><strong>Code Quality:</strong> Facilitates peer review to catch bugs, improve design, and ensure consistency.</li> + <li><strong>Knowledge Sharing:</strong> Team members learn from each other's code and provide feedback.</li> + <li><strong>Gatekeeping:</strong> Ensures changes meet standards and pass tests before entering the main codebase.</li> + <li><strong>Discussion Record:</strong> Provides a history of decisions and discussions related to the changes.</li> + </ul> + </div> + </div> + </div> + <div class="col-lg-4 col-md-6"> + <div class="info-card" id="card-workflow-cicd"> + <div class="card-body"> + <h5><i class="bi bi-gear-wide-connected"></i> CI/CD Integration</h5> + <div class="card-content-wrapper"> + <p class="summary">VCS triggers <span class="term">Continuous Integration</span> (automated build/test) and <span class="term">Continuous Delivery/Deployment</span> pipelines, automating the software delivery process.</p> + <button class="btn btn-sm details-toggle" type="button" data-bs-toggle="collapse" data-bs-target="#collapseWorkflow3" aria-expanded="false" aria-controls="collapseWorkflow3"> + Explore <i class="bi bi-chevron-down"></i> + </button> + </div> + </div> + <div class="collapse collapse-content" id="collapseWorkflow3"> + <h6>Continuous Integration (CI)</h6> + <p>The practice of frequently merging code changes into a central repository, after which automated builds and tests are run.</p> + <ul> + <li><strong>Trigger:</strong> Typically runs on every push to a branch or opening/updating a PR/MR.</li> + <li><strong>Goal:</strong> Detect integration errors early by automatically building the software and running automated tests (unit, integration).</li> + <li><strong>Benefit:</strong> Faster feedback loop, reduced integration problems, improved code quality.</li> + </ul> + <h6>Continuous Delivery (CD) / Continuous Deployment (CD)</h6> + <p>Extends CI by automating the release process.</p> + <ul> + <li><strong>Continuous Delivery:</strong> Automatically builds, tests, and prepares code changes for release to production. The final deployment to production might still be a manual step.</li> + <li><strong>Continuous Deployment:</strong> Automatically deploys every validated change to production without manual intervention.</li> + <li><strong>Trigger:</strong> Typically runs after CI succeeds on specific branches (e.g., <code>main</code>) or merges.</li> + <li><strong>Benefit:</strong> Faster, reliable releases; reduced manual deployment effort and errors.</li> + </ul> + <h6>Role of VCS</h6> + <p>VCS events (push, merge, tag creation) act as the primary triggers for CI/CD pipelines provided by platforms like GitHub Actions, GitLab CI/CD, Bitbucket Pipelines, Azure Pipelines, or dedicated tools like Jenkins.</p> + </div> + </div> + </div> + </div> <!-- /.row --> + </div> <!-- /.schema-container --> + + <!-- 5. CHOOSING YOUR TOOLS --> + <div class="schema-container cat-choosing" data-section-id="section-choosing"> + <h2 class="section-title" id="section-choosing">Choosing Your Tools</h2> + <div class="row"> + <div class="col-12"> + <div class="info-card" id="card-choosing"> + <div class="card-body"> + <h5 class="text-center"><i class="bi bi-check2-square"></i> System & Platform Selection</h5> + <div class="card-content-wrapper"> + <p class="summary text-center">Choose <span class="term">Git</span> unless you have specific reasons for Mercurial. Select a <span class="term">Platform</span> based on ecosystem integration (Atlassian, Microsoft), desired features (CI/CD, security), community needs, and self-hosting requirements.</p> + <button class="btn btn-sm details-toggle mx-auto" type="button" data-bs-toggle="collapse" data-bs-target="#collapseChoosing" aria-expanded="false" aria-controls="collapseChoosing"> + Key Factors <i class="bi bi-chevron-down"></i> + </button> + </div> + </div> + <div class="collapse collapse-content" id="collapseChoosing"> + <h6>Choosing the VCS System (Git vs. Mercurial)</h6> + <ul> + <li><strong>Default Choice:</strong> <span class="term">Git</span> is the overwhelming industry standard. Choose Git for maximum compatibility, community support, tooling, and platform options.</li> + <li><strong>Consider Mercurial if:</strong> Your team strongly prefers its perceived simplicity, you need its specific branching model, or you are contributing to an existing Mercurial project (e.g., some parts of Meta). Be aware of declining platform support.</li> + </ul> + <h6>Choosing the Hosting Platform (GitHub vs. GitLab vs. Bitbucket vs. Azure DevOps)</h6> + <ul> + <li><strong>Community & Open Source:</strong> <span class="term">GitHub</span> is the leader. Its Actions CI/CD is very popular.</li> + <li><strong>Integrated DevOps & Self-Hosting:</strong> <span class="term">GitLab</span> excels if you want an all-in-one solution or need to host it yourself. Strong built-in CI/CD and security focus.</li> + <li><strong>Atlassian Ecosystem:</strong> <span class="term">Bitbucket</span> is the best choice if you rely heavily on Jira and other Atlassian tools.</li> + <li><strong>Microsoft Ecosystem & Enterprise:</strong> <span class="term">Azure DevOps</span> is ideal for teams deep in Azure, needing enterprise governance, or leveraging its mature Boards and Pipelines.</li> + <li><strong>CI/CD Needs:</strong> Evaluate the specifics of GitHub Actions, GitLab CI/CD, Bitbucket Pipelines, and Azure Pipelines based on your complexity and integration requirements.</li> + <li><strong>Pricing & Tiers:</strong> Compare free tier limitations (users, private repos, CI/CD minutes, storage) and paid plan costs based on your team size and usage.</li> + <li><strong>User Interface & Experience:</strong> Team preference for the platform's look, feel, and ease of use can be a factor.</li> + </ul> + <h6>Polyglot Approach?</h6> + <p>While possible to use different platforms for different projects, most organizations standardize on one primary hosting platform for consistency, billing, and user management, while potentially integrating specialized tools from other ecosystems if needed.</p> + </div> + </div> + </div> + </div> <!-- /.row --> + </div> <!-- /.schema-container --> + +</div> <!-- /container --> + +<footer class="container text-center"> + <!-- Update with your name/year --> + <p>© 2024 Your Name Here</p> +</footer> + +<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js"></script> +<script> +document.addEventListener('DOMContentLoaded', () => { + const mainContainer = document.getElementById('main-container'); + let currentHoverState = { card: null }; // Simplified state + + // --- Clear Hover State --- + function clearHoverState(forceClear = false) { + const isMouseStillOverCard = currentHoverState.card && currentHoverState.card.matches(':hover'); + + if (forceClear || !isMouseStillOverCard) { + mainContainer.classList.remove('is-dimmed'); + if(currentHoverState.card) { + currentHoverState.card.classList.remove('is-highlighted'); + const oldSchemaContainer = currentHoverState.card.closest('.schema-container'); + if (oldSchemaContainer) { + oldSchemaContainer.classList.remove('is-highlighted-section'); + const oldTitle = oldSchemaContainer.querySelector('.section-title'); + if (oldTitle) oldTitle.style.opacity = ''; + } + } + currentHoverState = { card: null }; + } + } + + // --- Apply Hover State --- + function applyHoverState(card) { + if (!card || card === currentHoverState.card) return; + + clearHoverState(true); // Force clear previous state + + const schemaContainer = card.closest('.schema-container'); + + // Set new state + currentHoverState.card = card; + mainContainer.classList.add('is-dimmed'); + card.classList.add('is-highlighted'); + if (schemaContainer) { + schemaContainer.classList.add('is-highlighted-section'); + const title = schemaContainer.querySelector('.section-title'); + if (title) title.style.opacity = '1'; // Ensure title is fully visible + } + } + + // --- Event Listeners using Event Delegation --- + mainContainer.addEventListener('mouseover', (event) => { + const targetCard = event.target.closest('.info-card'); + if (targetCard && targetCard !== currentHoverState.card) { + applyHoverState(targetCard); + } + }); + + mainContainer.addEventListener('mouseout', (event) => { + // If mouse leaves the container or moves from a card to a non-card area + if (!mainContainer.contains(event.relatedTarget) || + (event.target.classList.contains('info-card') && !event.relatedTarget?.closest('.info-card'))) + { + // Delay slightly to avoid flicker when moving between adjacent cards or card elements + setTimeout(() => { + const isOverAnotherCard = mainContainer.querySelector('.info-card:hover'); + if (!isOverAnotherCard) { + clearHoverState(true); + } + }, 50); + } + }); + + // --- Toggle Chevron Icons on Collapse Buttons --- + const collapseToggles = document.querySelectorAll('.details-toggle'); + collapseToggles.forEach(button => { + const targetId = button.getAttribute('data-bs-target'); + const targetCollapse = document.querySelector(targetId); + const icon = button.querySelector('.bi'); + + if (targetCollapse && icon) { + // Set initial icon state based on whether the collapse element starts shown + if (targetCollapse.classList.contains('show')) { + icon.classList.remove('bi-chevron-down'); + icon.classList.add('bi-chevron-up'); + } else { + icon.classList.remove('bi-chevron-up'); + icon.classList.add('bi-chevron-down'); + } + + // Listen to Bootstrap collapse events to toggle icon + targetCollapse.addEventListener('show.bs.collapse', () => { + icon.classList.remove('bi-chevron-down'); + icon.classList.add('bi-chevron-up'); + }); + targetCollapse.addEventListener('hide.bs.collapse', () => { + icon.classList.remove('bi-chevron-up'); + icon.classList.add('bi-chevron-down'); + }); + } + }); +}); +</script> +</body> +</html> \ No newline at end of file