Saltar al contenido
GitTree

Lección 6 · trabajo diario

Lea la comparación antes de juzgar un cambio.

Convierta al héroe en un proyecto estático ejecutable y luego distinga las diferencias de trabajo, puestas en escena y registradas. Inspeccione una variante de imagen determinista separada sin agregar una confirmación de imagen al historial del curso continuo.

Progreso guardado en este navegador.

La reproducción carga el vídeo de YouTube (modo de privacidad mejorada).

Narración en inglés · English and Arabic subtítulos

Abre la página del vídeoVer en YouTube

lo que aprenderás

  • Nombra ambos lados de una comparación de texto e interpreta las adiciones y eliminaciones.
  • Explique por qué un archivo sin seguimiento puede no estar presente en un git diff normal.
  • Compare imágenes visualmente sin pretender que Git proporciona un parche de imagen textual.
  • Agregue y verifique las pequeñas comprobaciones locales antes de enviar la página ejecutable.

Antes de empezar

Comienzas donde terminó la lección 5: el principal original con un compromiso de héroe. HEAD/index contiene HTML-01; index.html de trabajo contiene HTML-01-WORKING. No existe ningún control remoto. Conserve esa edición de línea de soporte en HTML-02; no lo descartes.

El vídeo se grabó con Git 2.52.0, Nodo 22.22.0, npm 10.9.4 y GitTree 2.0 en Ubuntu 24.04: los diez archivos se guardaron en el propio editor de GitTree, se prepararon y confirmaron en la aplicación, y las comprobaciones del terminal se ejecutaron con lo que creó la aplicación, o con copias separadas para el estado antes de la preparación y para la imagen. Las comprobaciones del Nodo pasaron en el Nodo 22, la versión que declara el proyecto. No se ejecutó nada en macOS o Windows, y Ubuntu es el único sistema Linux registrado. El piso de Git inspeccionado de GitTree es 2.39.0. Una vez que haya iniciado sesión en GitTree, Git local estará en el plan gratuito y no necesita credenciales de proveedor ni API.

Concepto

Una diferencia responde a una pregunta sobre two snapshots, no a si un archivo es "bueno". El git diff ordinario compara índice → árbol de trabajo; git diff --cached compara HEAD → index; git diff HEAD compara HEAD → árbol de trabajo. Un signo más marca el texto del lado nuevo y un signo menos marca el texto del lado antiguo, no aprobación ni culpa. Lea referencia de diferencias de Git para conocer la semántica de comparación.

Un archivo sin seguimiento no tiene una entrada de índice normal. Por lo tanto, la diferencia ordinaria vacía no prueba que no exista ningún archivo nuevo. Revise también el estado y el contenido de los archivos recién agregados. Después de preparar un archivo nuevo, se puede revisar su adición completa en la comparación en caché.

Cambiar Inline/Split/Hunk, ajuste, modo de imagen o visualización de espacios en blanco ocultos cambia el view, no los bytes del archivo, el índice, las confirmaciones o las referencias remotas. La puesta en escena cambia el índice. La confirmación normal final mueve el main local; No hay cambios en el estado del servidor.

Entradas de proyecto completamente ejecutables

Mantenga README-01 sin cambios. Reemplace index.html con HTML-02 y cree todos los archivos restantes a continuación con UTF-8/LF y una nueva línea final. El .gitignore mínimo es intencional: la salida de la compilación no debe ingresar accidentalmente esta primera confirmación ejecutable. Una política de ignorancia más amplia llegará más tarde. Estas son cargas útiles de documentos del curso, no archivos de aplicaciones instalados en el repositorio web.

index.html — HTML-02

Extracto del archivo · html
<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>GitTree Features — course demo</title>
  <link rel="stylesheet" href="styles.css">
</head>
<body>
  <header class="site-header">
    <a href="#main">GitTree Features</a>
  </header>
  <main id="main">
    <section class="hero" aria-labelledby="hero-title">
      <p class="eyebrow">GitTree Learn demo project</p>
      <h1 id="hero-title">Understand every change.</h1>
      <p id="hero-copy">Choose one change, then check what Git saved.</p>
    </section>
    <section class="features" aria-labelledby="features-title">
      <h2 id="features-title">Follow your work</h2>
      <div class="cards">
        <article class="feature-card">
          <h3>History</h3>
          <p>Read commits and branches together.</p>
        </article>
        <article class="feature-card">
          <h3>Changes</h3>
          <p>Review the exact content selected for a commit.</p>
        </article>
        <article class="feature-card">
          <h3>Recovery</h3>
          <p>Inspect the scope of a recovery point before using it.</p>
        </article>
      </div>
    </section>
  </main>
  <footer><p>Built by a fictional team for GitTree Learn.</p></footer>
  <script type="module" src="site.js"></script>
</body>
</html>

estilos.css — CSS-01

Extracto del archivo · css
:root {
  color-scheme: light;
  --page: #f7f8fa;
  --surface: #ffffff;
  --text: #17212e;
  --link: #154ab5;
  --line: #bac4d0;
}

* {
  box-sizing: border-box;
}

body {
  margin: 0;
  background: var(--page);
  color: var(--text);
  font: 1rem/1.6 system-ui, sans-serif;
}

a {
  color: var(--link);
}

.site-header,
main,
footer {
  width: min(68rem, 100% - 2rem);
  margin-inline: auto;
}

.site-header {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: 1rem;
  padding-block: 1rem;
}

.hero {
  max-width: 44rem;
  padding-block: 3rem;
}

h1 {
  font-size: clamp(2rem, 5vw, 3.5rem);
  line-height: 1.2;
}

.cards {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(16rem, 100%), 1fr));
  gap: 1rem;
}

.feature-card {
  padding: 1rem;
  border: 1px solid var(--line);
  border-radius: 0.5rem;
  background: var(--surface);
}

section {
  margin-block-end: 2rem;
}

button,
input {
  font: inherit;
}

button,
input {
  padding: 0.5rem 0.75rem;
}

:focus-visible {
  outline: 3px solid var(--link);
  outline-offset: 3px;
}

form {
  display: grid;
  max-width: 28rem;
  gap: 0.5rem;
}

sitio.js — JS-01

Extracto del archivo · javascript
export function validateEmail(value) {
  return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value.trim());
}

if (typeof document !== 'undefined') {
  const form = document.querySelector('#signup-form');
  const email = document.querySelector('#demo-email');
  const result = document.querySelector('#signup-result');
  const toggle = document.querySelector('#theme-toggle');

  if (form && email && result) {
    form.addEventListener('submit', (event) => {
      event.preventDefault();
      result.textContent = validateEmail(email.value)
        ? 'Valid format. This demo sent nothing.'
        : 'Enter a complete fictional email address.';
    });
  }

  if (toggle) {
    toggle.addEventListener('click', () => {
      const enabled = document.documentElement.dataset.theme !== 'dark';
      document.documentElement.dataset.theme = enabled ? 'dark' : 'light';
      toggle.setAttribute('aria-pressed', String(enabled));
      toggle.textContent = enabled ? 'Use light mode' : 'Use dark mode';
    });
  }
}

paquete.json — PAQUETE-01

Extracto del archivo · json
{
  "name": "gittree-features",
  "version": "0.1.0",
  "private": true,
  "type": "module",
  "engines": {
    "node": ">=22"
  },
  "scripts": {
    "lint": "node scripts/lint.mjs",
    "test": "node --test",
    "build": "node scripts/build.mjs",
    "start": "node scripts/serve.mjs"
  }
}

paquete-lock.json - LOCK-01

Extracto del archivo · json
{
  "name": "gittree-features",
  "version": "0.1.0",
  "lockfileVersion": 3,
  "requires": true,
  "packages": {
    "": {
      "name": "gittree-features",
      "version": "0.1.0",
      "engines": {
        "node": ">=22"
      }
    }
  }
}

pruebas/sitio.test.mjs — PRUEBA-01

Extracto del archivo · javascript
import assert from 'node:assert/strict';
import test from 'node:test';

import { validateEmail } from '../site.js';

test('accepts the fictional team address', () => {
  assert.equal(validateEmail('maya@example.com'), true);
});

test('trims surrounding whitespace', () => {
  assert.equal(validateEmail('  leo@example.com  '), true);
});

test('rejects a missing domain', () => {
  assert.equal(validateEmail('omar@'), false);
});

test('rejects a missing local part', () => {
  assert.equal(validateEmail('@example.com'), false);
});

test('rejects spaces inside an address', () => {
  assert.equal(validateEmail('sara name@example.com'), false);
});

test('rejects input without an at sign', () => {
  assert.equal(validateEmail('priya.example.com'), false);
});

scripts/lint.mjs — LINT-01

Extracto del archivo · javascript
import { readFile } from 'node:fs/promises';

const files = ['index.html', 'styles.css', 'site.js'];
const problems = [];

for (const file of files) {
  const source = await readFile(file, 'utf8');
  if (!source.endsWith('\n')) problems.push(file + ': missing final newline');
  const lines = source.split('\n');
  for (const [index, line] of lines.entries()) {
    if (/[\t ]+$/.test(line)) {
      problems.push(file + ':' + (index + 1) + ': trailing whitespace');
    }
  }
}

if (problems.length > 0) {
  process.stderr.write(problems.join('\n') + '\n');
  process.exitCode = 1;
} else {
  process.stdout.write('Source formatting checks passed.\n');
}

scripts/build.mjs — BUILD-01

Extracto del archivo · javascript
import { copyFile, mkdir, readdir, stat } from 'node:fs/promises';
import path from 'node:path';

const output = path.resolve('dist');
const queue = ['index.html', 'styles.css', 'site.js', 'assets', 'vendor/snippets'];

await mkdir(output, { recursive: true });

while (queue.length > 0) {
  const source = queue.pop();
  let details;
  try {
    details = await stat(source);
  } catch (error) {
    if (error.code === 'ENOENT' && (source === 'assets' || source === 'vendor/snippets')) continue;
    throw error;
  }
  if (details.isDirectory()) {
    const entries = await readdir(source, { withFileTypes: true });
    for (const entry of entries) {
      if (entry.name !== '.git') queue.push(path.join(source, entry.name));
    }
    continue;
  }
  const target = path.join(output, source);
  await mkdir(path.dirname(target), { recursive: true });
  await copyFile(source, target);
}

process.stdout.write('Built the static site in dist/.\n');

scripts/serve.mjs — SERVE-01

Extracto del archivo · javascript
import { readFile, stat } from 'node:fs/promises';
import http from 'node:http';
import path from 'node:path';

const root = path.resolve('dist');
const port = Number(process.env.PORT ?? 8080);
const types = {
  '.html': 'text/html; charset=utf-8',
  '.css': 'text/css; charset=utf-8',
  '.js': 'text/javascript; charset=utf-8',
  '.bmp': 'image/bmp',
};

await stat(path.join(root, 'index.html'));

const server = http.createServer(async (request, response) => {
  try {
    const address = new URL(request.url, 'http://localhost');
    const pathname = decodeURIComponent(address.pathname);
    const target = path.resolve(root, '.' + (pathname === '/' ? '/index.html' : pathname));
    const extension = path.extname(target);
    if (!target.startsWith(root + path.sep) || !Object.hasOwn(types, extension)) {
      response.writeHead(404).end('Not found');
      return;
    }
    const body = await readFile(target);
    response.writeHead(200, {
      'Content-Type': types[extension],
      'X-Content-Type-Options': 'nosniff',
    }).end(body);
  } catch {
    response.writeHead(404).end('Not found');
  }
});

server.listen(port, '127.0.0.1', () => {
  process.stdout.write('Demo site: http://127.0.0.1:' + port + '\n');
});

process.on('SIGINT', () => server.close());
process.on('SIGTERM', () => server.close());

.gitignore - IGNORAR-CONSTRUIR

Extracto del archivo · gitignore
dist/

En GitTree

  1. En el repositorio original, use Command Palette… (Comando/Ctrl+Shift+P) → Show Working Changes. Haga clic en index.html en Unstaged Files. Antes de reemplazarlo, identifique la edición de la línea de soporte retenida de la lección 5.
  2. Utilice Show Files (Comando/Ctrl+Mayús+E); Enfoque index.html en el árbol de archivos y presione Enter. Reemplace su contenido de trabajo con HTML-02, luego Save (Comando/Ctrl+S en el editor). Espere a que se borre el indicador de no guardado.
  3. Para cada uno de los archivos completos anteriores: paleta New File… → Path from the project folder, escriba la ruta relativa a la raíz exacta → Create, pegue su propio cuerpo completo → Save. Las rutas anidadas crean los directorios que faltan. Rechazar un archivo existente significa inspeccionar ese archivo, no sobrescribir un trabajo desconocido.
  4. Back to Graph → paleta Show Working Changes. Revise los archivos sin seguimiento, así como index.html. Utilice Stage File exactamente en las diez rutas modificadas mencionadas anteriormente, no generó salida dist. Deje el archivo README existente intacto.
  5. Haga clic en cada ruta debajo de Staged Files. Utilice Hunk, Inline y Split según estén disponibles en Diff view. Los equivalentes de paleta son Show Diff as Hunks, Show Diff Inline, Show Diff Side by Side. Next change es F7; Previous change es Mayús+F7. Lo viejo sigue siendo izquierda y lo nuevo derecha en Split, incluso en árabe.
  6. Inspeccione Ignore whitespace / paleta Ignore Whitespace in Diffs y luego restáurelo. Los espacios en blanco ocultos no son contenido ausente; La selección parcial puede no estar disponible cuando los cambios de espacios en blanco están ocultos. No utilice un filtro de visualización como evidencia de un índice limpio.
  7. Ejecute las comprobaciones nativas a continuación en la carpeta original. Luego ingrese Resumen feat: add styling and local project checks, mantenga desactivado modificar/push/empty/skip-hooks y elija Commit Changes to 10 Files. Comando/Ctrl+Entrar es un envío alternativo, no un segundo paso. Verifique dos confirmaciones y limpie el estado del seguimiento.

en la terminal

En el punto de control input, esta consulta de solo lectura captura la edición de la lección 5 aún no confirmada:

Command · bash
git diff -- index.html

Salida total observada:

Salida
diff --git a/index.html b/index.html
index 5470374..27f8718 100644
--- a/index.html
+++ b/index.html
@@ -13,7 +13,7 @@
     <section class="hero" aria-labelledby="hero-title">
       <p class="eyebrow">GitTree Learn demo project</p>
       <h1 id="hero-title">Understand every change.</h1>
-      <p id="hero-copy">A clear view of Git history.</p>
+      <p id="hero-copy">Choose one change, then check what Git saved.</p>
     </section>
   </main>
   <footer><p>Built by a fictional team for GitTree Learn.</p></footer>

Después de guardar todas las cargas útiles, antes de la preparación:

Command · bash
git status --short
Salida
 M index.html
?? .gitignore
?? package-lock.json
?? package.json
?? scripts/
?? site.js
?? styles.css
?? tests/

Las entradas del directorio scripts/ y tests/ están agrupadas en estado sin seguimiento, no hay evidencia de que sus cuerpos de archivos hayan sido revisados.

Ejecutar controles; no se necesita instalación de dependencia o red porque estos scripts usan solo elementos integrados de Node:

Command · bash
npm run --silent lint
npm test -- --test-reporter=tap
npm run --silent build
git check-ignore dist/index.html

Salida de pelusa observada:

Salida
Source formatting checks passed.

Observado test-summary excerpt, excluyendo el tiempo por prueba:

Salida
# tests 6
# suites 0
# pass 6
# fail 0
# cancelled 0
# skipped 0
# todo 0

Salidas observadas de compilación e ignoradas, un comando cada una:

Salida
Built the static site in dist/.
dist/index.html

El script de inicio npm escrito vincula el loopback y sirve dist. Es de larga duración; No confunda un proceso de servidor con una prueba aprobada. Su comportamiento HTTP en vivo aún necesita una verificación del entorno de grabación; Aquí no se afirma ninguna toma del servidor.

Alternativa de etapa/compromiso nativo, solo si la aplicación aún no ha realizado esas mutaciones:

Command · bash
git add -- .gitignore index.html styles.css site.js package.json package-lock.json tests/site.test.mjs scripts/lint.mjs scripts/build.mjs scripts/serve.mjs
git diff --cached --stat
git commit --quiet -m "feat: add styling and local project checks"
git rev-list --count HEAD
git status --short

El compromiso silencioso tuvo éxito en silencio; el recuento imprime 2 y el estado corto final está vacío. La estadística es una ayuda para la revisión, no un sustituto de la lectura de los diez cuerpos de los archivos. dist se ignora, no se confirma; no se agregó ningún control remoto.

Variante de comparación de imágenes separada

Prepare un copy of this same GitTree Features checkpoint aislado, nunca un segundo ejemplo no relacionado ni el original continuo. Agregue activos/diff-card.png con los bytes anteriores, realice una confirmación claramente etiquetada solo para dispositivos y luego reemplace sus bytes de trabajo con después. Estos archivos Markdown no entregan ningún archivo de imagen ni medio final.

Ambos PNG tienen una mitad izquierda azul. Antes tiene una mitad derecha blanca; después tiene un cuarto verde en la parte inferior derecha. Bytes completos exactos:

VersiónDimensionesbytesSHA-256
antes64 × 641629a09ba97c890da0d542166ba17882bea8f7bf9b9bd4f5ec068a156f6b7256773
después64 × 641712ddabb4b9859aa53ff9c433a48cb7db0213e184b425a86fef20d8502eed8974f

before — full PNG Base64 bytes

Salida
iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAAAaUlEQVR4nO3QAQkAAAjAMEtYyr7m0xgi7PACi6yey68LAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA4D/AAqNletEZdhfWAAAAAElFTkSuQmCC

after — full PNG Base64 bytes

Salida
iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAAAcklEQVR4nO3QQQ0AIBAEsTOBA9QQ1OANfaCC7INOMgZabeyTPF0BAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJ7f14wOAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAfABwAT8dDllEqFx1AAAAAElFTkSuQmCC

Un operador de grabación puede decodificar una carga útil a la vez en la copia aislada:

Command · bash
node --input-type=module -e "import {mkdirSync,writeFileSync} from 'node:fs'; mkdirSync('assets',{recursive:true}); writeFileSync('assets/diff-card.png',Buffer.from('<selected-full-base64>','base64'));"

Reemplace el marcador de posición del soporte angular con una carga útil completa, sin los soportes. Decodificar antes, preparar/confirmar el dispositivo, luego decodificar después sin realizar la preparación. Los recuentos/resúmenes de bytes proporcionados identifican cada estado; Nunca reutilice una captura de pantalla de una imagen fabricada.

En esa variante, nativo:

Command · bash
git diff --numstat -- assets/diff-card.png

Observado en la sonda binaria:

Salida
-	-	assets/diff-card.png

Los guiones significan que Git informa datos binarios, no cero píxeles modificados.

En la aplicación real: Show Working Changes → haga clic en activos/diff-card.png en Archivos no preparados → Side by side → Swipe, mueva Swipe position con las teclas de flecha → Onion skin, cambie After image opacity. Equivalentes de paleta: Show Image Changes Side by Side, Show Image Changes with a Swipe, Show Image Changes as Onion Skin. En realidad, ambas partes deben decodificar; ausente/demasiado grande/no es una imagen es un estado válido diferente, no una razón para falsificar la imagen. La fuente reconoce PNG/JPEG/GIF/WebP, not BMP; Al dispositivo LFS BMP posterior no se le debe prometer esta vista de imagen.

Regrese al original, el punto de control para la siguiente lección. Los recursos/compromisos adicionales de la variante de imagen nunca entran en la historia canónica.

Resultado

Dos confirmaciones en main; README más las diez entradas declaradas rastreadas; los archivos de índice/trabajo concuerdan con HEAD; La dist generada puede existir pero se ignora. Sin fijación de imagen ni control remoto en el árbol canónico.

Errores comunes

  • Vacíe las diferencias ordinarias mientras no se realiza el seguimiento de los archivos nuevos: inspeccione el estado y las adiciones por etapas.
  • Lectura de --stat como corrección: inspecciona el contenido real y ambos puntos finales de comparación.
  • Tratar la ocultación de espacios en blanco como si se eliminaran espacios en blanco: es solo una vista.
  • Comprometer dist o el dispositivo del lado de la imagen: preparar la lista canónica exacta.

Si algo sale mal

Una pelusa/prueba/compilación fallida es una señal real; retenga su salida y corrija solo la entrada de demostración indicada. No omita comprobaciones ni elimine carpetas desconocidas. Una imagen bloqueada/no compatible debe seguir siendo un aviso binario/de tamaño honesto hasta que se concilie su formato/tamaño real. Cancele una solicitud de selección parcial obsoleta y vuelva a cargar la diferencia actual en lugar de forzar un parche.

Comprueba tu comprensión

Responda cada pregunta y luego lea por qué. Las preguntas marcadas como "Obligatorias" cuentan para completar la lección.

  1. Pregunta 1 de 6

    ¿Con qué se compara el git diff ordinario?

    Elija una respuesta.

  2. Pregunta 2 de 6

    ¿Qué acciones dejan las instantáneas del repositorio sin cambios?

    Elija cada respuesta que corresponda.

  3. Pregunta 3 de 6
    Requerido

    El nuevo site.js no tiene seguimiento. La diferencia ordinaria está vacía para ello. ¿Está ausente?

    Elija una respuesta.

  4. Pregunta 4 de 6
    Requerido

    Si prepara ese nuevo archivo, ¿dónde se puede revisar su adición completa?

    Elija una respuesta.

  5. Pregunta 5 de 6

    La imagen numstat imprime dos guiones. ¿Qué puedes concluir?

    Elija una respuesta.

  6. Pregunta 6 de 6
    Requerido

    Verificar el punto de control terminado. ¿Qué hechos se requieren juntos?

    Elija cada respuesta que corresponda.

0 de 6 correcto

Responda correctamente las preguntas requeridas para completar la lección.

Comprobado en este navegador.

Practica

En el original, verifique el recuento 2, la diferencia en funcionamiento/en caché vacía y la dist ignorada. En la variante de imagen separada, indique qué cuadrante cambió y por qué numstat nativo informa guiones. Entrada modificada: si un archivo nuevo permanece sin seguimiento en lugar de preparado, predice que la diferenciación ordinaria aún puede omitirlo.

Su propia confirmación: el sitio no puede ver su computadora.

Para completar la lección, responde correctamente a las preguntas requeridas y confirma el ejercicio práctico.

Resumen

  • Nombra ambos puntos finales antes de leer una diferencia.
  • Las vistas de texto, binarias e imágenes decodificadas proporcionan evidencia diferente.
  • Los controles y la puesta en escena exacta protegen el punto de control ejecutable.

Términos del glosario introducidos

Diferencia — فروق; trozo — كتلة; índice — الفهرس; árbol de trabajo — مجلد العمل; binario — ثنائي; sin seguimiento — غير مُتتبَّع.

Transcripción del vídeo

La narración del vídeo, cue a cue.

Mostrar la transcripción
  1. Lee la comparación antes de juzgar el cambio.
  2. La línea de héroe posterior todavía está contenido de trabajo, no una nueva confirmación.
  3. Diferencias ordinarias y escenificadas comparar diferentes instantáneas.
  4. Agregue las entradas ejecutables completas, manteniendo la edición de línea de soporte existente.
  5. Es posible que falten archivos nuevos del normal. diff hasta que ingresan al índice.
  6. Preparar los insumos declarados, no se generó salida de compilación.
  7. El diseño cambia tu vista, no los bytes comparados.
  8. Siga el texto circundante antes Interpretar una adición o eliminación.
  9. Ocultar espacios en blanco no es eliminar un cambio de espacio en blanco.
  10. Ejecute el formato local comprobar antes de comprometerse.
  11. Las seis validaciones de entrada Las pruebas pasan en este accesorio.
  12. La salida de la compilación pertenece al directorio ignorado, no la confirmación.
  13. Confirmar lo revisado proyecto ejecutable localmente.
  14. Verifique dos confirmaciones y ninguna diferencia restante rastreada.
  15. Utilice una copia separada para comparar imágenes, no el punto de control continuo.
  16. Las dos cargas útiles PNG exactas Identificar los estados de la imagen.
  17. Compara los lados nombrados y sus dimensiones reales.
  18. Mueva el divisor sin cambiando cualquiera de los archivos.
  19. La opacidad cambia la comparación, no los píxeles guardados.
  20. El resumen binario de Git no es un recuento de píxeles modificados.
  21. Un archivo no compatible o de gran tamaño debe mantener su aviso honesto.
  22. Mantenga la imagen fija fuera de la historia canónica.
  23. Predice qué comparación muestra un archivo recién preparado.
  24. A continuación, seleccione trozos y líneas. sin descartar otros trabajos.