Skip to content

Instantly share code, notes, and snippets.

@pcorpet
Created February 27, 2026 12:45
Show Gist options
  • Select an option

  • Save pcorpet/048416b40737bbd66d095bac811091c1 to your computer and use it in GitHub Desktop.

Select an option

Save pcorpet/048416b40737bbd66d095bac811091c1 to your computer and use it in GitHub Desktop.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>yarn.lock in Git</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
padding: 20px;
}
.presentation {
background: white;
border-radius: 12px;
box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3);
width: 95vw;
height: 90vh;
display: flex;
flex-direction: column;
}
.slides-container {
flex: 1;
position: relative;
overflow: hidden;
}
.slide {
position: absolute;
width: 100%;
height: 100%;
opacity: 0;
transition: opacity 0.5s ease-in-out;
padding: 60px;
display: flex;
flex-direction: column;
justify-content: center;
overflow-y: auto;
}
.slide.active {
opacity: 1;
}
.slide h1 {
font-size: 3.5em;
color: #667eea;
margin-bottom: 30px;
}
.slide h2 {
font-size: 2.5em;
color: #667eea;
margin-bottom: 40px;
}
.code-block {
background: #f5f5f5;
border-left: 4px solid #667eea;
padding: 15px;
margin: 10px 0;
font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;
font-size: 0.9em;
border-radius: 4px;
overflow-x: auto;
line-height: 1.4;
white-space: pre;
}
.code-label {
font-weight: 600;
color: #667eea;
font-size: 0.9em;
margin-bottom: 8px;
text-transform: uppercase;
}
.file-comparison {
display: flex;
gap: 40px;
margin-top: 30px;
}
.file-column {
flex: 1;
}
.file-column h3 {
font-size: 1.3em;
color: #764ba2;
margin-bottom: 15px;
font-weight: 600;
}
.title-slide {
justify-content: center;
align-items: center;
text-align: center;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
}
.title-slide h1 {
color: white;
font-size: 4em;
margin-bottom: 20px;
}
.title-slide p {
color: #e0e0e0;
font-size: 1.5em;
}
.highlight-yellow {
background: #fff3cd;
padding: 20px;
border-radius: 8px;
margin: 20px 0;
border-left: 4px solid #ffc107;
font-size: 0.95em;
line-height: 1.6;
}
.highlight-red {
background: #ffe0e0;
padding: 20px;
border-radius: 8px;
margin: 20px 0;
border-left: 4px solid #ff4444;
font-size: 0.95em;
line-height: 1.6;
}
.highlight-green {
background: #e0ffe0;
padding: 20px;
border-radius: 8px;
margin: 20px 0;
border-left: 4px solid #44aa44;
font-size: 0.95em;
line-height: 1.6;
}
.arrow {
text-align: center;
font-size: 2em;
color: #667eea;
margin: 15px 0;
}
.controls {
display: flex;
justify-content: space-between;
align-items: center;
padding: 20px 40px;
background: #f9f9f9;
border-top: 1px solid #eee;
}
button {
background: #667eea;
color: white;
border: none;
padding: 12px 24px;
border-radius: 6px;
font-size: 1em;
cursor: pointer;
transition: background 0.3s;
}
button:hover {
background: #764ba2;
}
button:disabled {
background: #ccc;
cursor: not-allowed;
}
.slide-counter {
color: #667eea;
font-weight: 600;
font-size: 1.1em;
}
.two-row {
display: flex;
flex-direction: column;
gap: 20px;
}
.change-indicator {
display: inline-block;
background: #ffe0e0;
color: #cc0000;
padding: 2px 8px;
border-radius: 3px;
font-size: 0.85em;
margin-left: 10px;
font-weight: 600;
}
.unchanged {
opacity: 0.6;
}
</style>
</head>
<body>
<div class="presentation">
<div class="slides-container">
<!-- Slide 1: Title -->
<div class="slide active title-slide">
<div>
<h1>yarn.lock in Git</h1>
<p>Reproducible dependencies</p>
</div>
</div>
<!-- Slide 2: Dependencies Definition -->
<div class="slide">
<h2>Dependencies Definition</h2>
<div class="file-comparison">
<div class="file-column">
<h3>package.json</h3>
<div class="code-label">What you want</div>
<div class="code-block">"react": "19.2.4"</div>
<p style="margin-top: 10px; font-size: 0.95em; color: #666;">Exact or range</p>
</div>
<div class="arrow">→</div>
<div class="file-column">
<h3>yarn.lock</h3>
<div class="code-label">What got installed</div>
<div class="code-block">version: 19.2.4
resolution: "react@npm:19.2.4"
checksum: 10/abc123def456...
dependencies:
loose-envify: "npm:^1.4.0"</div>
<p style="margin-top: 10px; font-size: 0.95em; color: #666;">Exact version + hash</p>
</div>
</div>
<div class="highlight-yellow">
One generates from the other. Both are essential.
</div>
</div>
<!-- Slide 3: Modifying package.json -->
<div class="slide">
<h2>Modify package.json</h2>
<div class="two-row">
<div>
<div class="code-label">Change in package.json:</div>
<div class="code-block">"react": "19.2.4" → "react": "20.0.0"</div>
</div>
<div class="arrow">↓ yarn install ↓</div>
<div>
<div class="code-label">yarn.lock updates:</div>
<div class="code-block">version: 20.0.0 <span class="change-indicator">CHANGED</span>
resolution: "react@npm:20.0.0"
checksum: 10/xyz789abc... <span class="change-indicator">CHANGED</span>
dependencies:
loose-envify: "npm:^1.4.0"</div>
</div>
</div>
<div class="highlight-yellow">
Commit both files together
</div>
</div>
<!-- Slide 4: Deleting yarn.lock -->
<div class="slide">
<h2>Delete yarn.lock & Recreate</h2>
<div class="two-row">
<div>
<div class="code-label">Delete yarn.lock</div>
<div class="code-block">$ rm yarn.lock</div>
</div>
<div class="arrow">↓ yarn install (Today) ↓</div>
<div>
<div class="code-label">Creates new yarn.lock with latest available</div>
<div class="code-block">version: 19.2.5
checksum: 10/aaa111bbb...</div>
</div>
<div class="arrow">↓ yarn install (Next week) ↓</div>
<div>
<div class="code-label">Different result!</div>
<div class="code-block">version: 19.2.7
checksum: 10/ccc333ddd...</div>
</div>
</div>
<div class="highlight-red">
⚠️ Inconsistent installs, "works on my machine" returns
</div>
</div>
<!-- Slide 5: Security Patch Upgrades -->
<div class="slide">
<h2>Security Patch Upgrade</h2>
<div class="two-row">
<div>
<div class="code-label">package.json (unchanged)</div>
<div class="code-block">"react": "19.2.4"</div>
</div>
<div class="arrow">↓ yarn upgrade react ↓</div>
<div>
<div class="code-label">yarn.lock (patches only)</div>
<div class="code-block">version: 19.2.8 <span class="change-indicator">PATCHED</span>
resolution: "react@npm:19.2.8"
checksum: 10/eee444fff... <span class="change-indicator">CHANGED</span></div>
</div>
</div>
<div class="highlight-green">
Safe, minimal changes, easy to review in PR
</div>
</div>
<!-- Slide 6: Python Parallel -->
<div class="slide">
<h2>Same Pattern Everywhere</h2>
<div class="file-comparison">
<div class="file-column">
<h3>JavaScript/Node</h3>
<div class="code-block">package.json
+
yarn.lock</div>
</div>
<div class="file-column" style="text-align: center; display: flex; align-items: center; justify-content: center;">
<div style="font-size: 2em; color: #667eea; font-weight: 600;">= Principle</div>
</div>
<div class="file-column">
<h3>Python</h3>
<div class="code-block">pyproject.toml
+
poetry.lock</div>
</div>
</div>
<div class="highlight-yellow" style="margin-top: 30px; text-align: center;">
Commit both. Always. Same everywhere.
</div>
<div class="highlight-green" style="margin-top: 20px; font-size: 0.95em;">
<strong>New enforcement rule:</strong><br>
PRs cannot modify <code>yarn.lock</code> without modifying <code>package.json</code><br>
<em>Exception: PRs that modify ONLY yarn.lock (no other files allowed)</em>
</div>
</div>
<!-- Slide 7: Questions -->
<div class="slide" style="justify-content: center; align-items: center; text-align: center;">
<h1 style="font-size: 4em;">Questions?</h1>
</div>
</div>
<div class="controls">
<button id="prev" onclick="previousSlide()">← Previous</button>
<span class="slide-counter"><span id="current">1</span> / <span id="total">7</span></span>
<button id="next" onclick="nextSlide()">Next →</button>
</div>
</div>
<script>
let currentSlide = 0;
const slides = document.querySelectorAll('.slide');
const totalSlides = slides.length;
function showSlide(n) {
slides[currentSlide].classList.remove('active');
currentSlide = (n + totalSlides) % totalSlides;
slides[currentSlide].classList.add('active');
document.getElementById('current').textContent = currentSlide + 1;
document.getElementById('prev').disabled = currentSlide === 0;
document.getElementById('next').disabled = currentSlide === totalSlides - 1;
}
function nextSlide() {
if (currentSlide < totalSlides - 1) {
showSlide(currentSlide + 1);
}
}
function previousSlide() {
if (currentSlide > 0) {
showSlide(currentSlide - 1);
}
}
// Keyboard navigation
document.addEventListener('keydown', (e) => {
if (e.key === 'ArrowRight') nextSlide();
if (e.key === 'ArrowLeft') previousSlide();
});
// Initialize
showSlide(0);
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment