Portafolio Profesional
Portafolio profesional desarrollado para centralizar experiencia, habilidades, proyectos, servicios y contenido técnico en una plataforma moderna y escalable.
|
Backend Developer | Desarrollo de APIs seguras, automatización y soluciones backend escalables | Python • PHP • NestJs • NextJs • React • MySQL • PostgreSQL • AWS • Git • Linux | Divulgando conocimiento para todos

Experiencia y Skills
Experiencia profesional, formación académica y habilidades técnicas conectadas con soluciones backend, APIs e infraestructura.
Profesional independiente · Híbrido
jul 2024 - actualidad · 2 años 2 meses
Villahermosa, Tabasco, México
Desde 2024 he trabajado de manera independiente desarrollando solucion...
sep 2018 - actualidad · 8 años
Villahermosa, Tabasco, México
Desde 2018, brindo servicios tecnológicos y soporte técnico especializ...
1/5
Skills
1/5
Sobre mí
Backend, APIs, automatización e infraestructura pensada para resolver problemas reales.
Backend Developer enfocado en el desarrollo de APIs seguras, automatización de procesos y soluciones escalables. Me apasiona construir sistemas eficientes, desde la lógica del servidor y la arquitectura backend hasta la integración con bases de datos y servicios en la nube.
He participado en proyectos académicos y tecnológicos relacionados con plataformas digitales, marketplaces y soluciones orientadas a innovación y tecnología. Además, disfruto compartir contenido técnico sobre backend, bases de datos, APIs y arquitectura de software. Actualmente continúo fortaleciendo mis conocimientos y desarrollando soluciones modernas y escalables.
Cliente
API
Backend
DB
Cloud
Paso 1
Una persona entra a tu sitio, inicia sesión o realiza una acción.
Servicios
Servicios enfocados en backend, APIs, bases de datos, infraestructura cloud y mantenimiento de aplicaciones.
Proyectos
Una selección de proyectos donde aplico backend, APIs, bases de datos, infraestructura y desarrollo full stack.
Blog
Publicaciones técnicas sobre backend, APIs, bases de datos, seguridad, arquitectura y desarrollo de software.
Carrusel: ¿Por qué tantos lenguajes empiezan a contar desde 0? Slide 1 — Hook 🤔 Tienes una lista con 5 elementos: ["A", "B", "C", "D", "E"] Pero sus posiciones son: 0 1 2 3 4 Espera... ¿5 elementos pero el último está en la posición 4? 😵💫 Si nosotros contamos: 1, 2, 3, 4, 5 👉 ¿por qué en tantos lenguajes de programación todo empieza desde 0 ? Sígueme para más contenido de Backend 🚀 💬 Comenta tu experiencia o dudas. @hermanprimodev Slide 2 — Deja de pensar en “número” En lugar de preguntar: ❌ “¿Qué número de elemento es?” prueba con: 📍 “¿Qué tan lejos está del inicio?” [A] [B] [C] [D] [E] ↑ INICIO Para llegar a A : ➡️ avanzas 0 posiciones. Para llegar a B : ➡️ avanzas 1 . Para llegar a C : ➡️ avanzas 2 . 💡 De repente, el cero empieza a tener sentido. Sígueme para más contenido de Backend 🚀 💬 Comenta tu experiencia o dudas. @hermanprimodev Slide 3 — Ahora llévalo a memoria Supongamos que: 📦 Cada elemento ocupa 4 bytes 📍 El arreglo comienza en 1000 Podemos pensar en: dirección = inicio + índice × tamaño Entonces: array[0] → 1000 + 0×4 = 1000 array[1] → 1000 + 1×4 = 1004 array[2] → 1000 + 2×4 = 1008 👉 El índice 0 apunta naturalmente al inicio porque su desplazamiento es exactamente cero. Sígueme para más contenido de Backend 🚀 💬 Comenta tu experiencia o dudas. @hermanprimodev Slide 4 — Pero hay una trampa Esto NO significa que: ❌ “Las computadoras siempre cuentan desde cero.” El indexado desde cero es una convención muy común. La encontramos en lenguajes como: C C++ Java JavaScript Python Pero no es una ley universal. Existen lenguajes, estructuras y APIs que utilizan otras bases de indexación. 👉 Lo importante es entender qué representa el índice en el contexto que estás usando. Sígueme para más contenido de Backend 🚀 💬 Comenta tu experiencia o dudas. @hermanprimodev Slide 5 — Y de aquí nace un clásico 😅 Tienes: 5 elementos Pero los índices son: 0 1 2 3 4 Por eso solemos recorrerlos con una condición como: i < longitud y no: i <= longitud Porque con longitud = 5 : array[4] ✅ array[5] ❌ Equivocarte por una posición puede producir el famoso: ⚠️ off-by-one error Un pequeño +1 o -1 ... puede ser suficiente para romper tu lógica. Sígueme para más contenido de Backend 🚀 💬 Comenta tu experiencia o dudas. @hermanprimodev Slide 6 — array[0] ya no parece tan raro Cuando veas: array[0] no pienses: 🤨 “Dame el elemento número cero.” Piensa: 📍 “Dame el elemento que está a CERO posiciones del inicio.” [A] [B] [C] [D] [E] 0 1 2 3 4 ↑ 0 posiciones Ese pequeño cambio de perspectiva explica por qué el indexado desde cero encaja tan bien con desplazamientos. 🧠 El índice no tiene que representar cuántos elementos llevas contando. También puede representar qué tan lejos estás del comienzo. 🔥 El backend no se ve, pero sin él, nada funciona. Sígueme para más contenido de Backend 🚀 💬 ¿Recuerdas la primera vez que array[0] te hizo pensar “¿por qué esto empieza en cero?” 😅 @hermanprimodev Elegí construir el carrusel alrededor de un cambio de perspectiva: de “número de elemento” a “distancia desde el inicio” . Primero hacemos que el 0 parezca extraño y después usamos exactamente ese mismo 0 para que la explicación encaje visualmente. Dejé fuera más detalles históricos y de implementación porque el ejemplo de direcciones de memoria ya comunica la intuición principal. La precisión importante es que empezar desde cero no es una obligación del hardware ni de todos los lenguajes; es una convención muy extendida y especialmente natural cuando un índice se interpreta como desplazamiento.
🗑️ Borras una fotografía de tu computadora… pero eso no siempre significa que sus datos desaparezcan inmediatamente Tienes una fotografía llamada: vacaciones.jpg La eliminas. Después vacías la papelera. La buscas nuevamente. Ya no aparece. Desde la perspectiva del usuario parece bastante claro: “El archivo ya no existe.” Pero internamente la historia puede ser diferente. Dependiendo del sistema de archivos, del dispositivo de almacenamiento y de cómo se haya realizado la eliminación, los datos que formaban ese archivo podrían permanecer físicamente almacenados durante cierto tiempo. Entonces aparece una pregunta interesante: 👉 ¿Qué significa realmente “borrar” un archivo? 🧠 Primero: guardar un archivo implica mucho más que almacenar sus bytes Cuando guardas algo como: vacaciones.jpg el sistema no simplemente coloca la fotografía en algún lugar del disco y espera que luego puedas encontrarla. Necesita mantener información que describa ese archivo. Conceptualmente podríamos imaginar algo así: vacaciones.jpg ↓ metadatos ↓ ubicación de los datos ↓ almacenamiento El sistema de archivos puede mantener información como: Nombre del archivo. Tamaño. Fechas. Permisos. Ubicación o referencias hacia sus datos. Estado del espacio utilizado. La implementación exacta depende del sistema de archivos. NTFS, ext4, APFS y otros utilizan estructuras diferentes. Pero la idea general permanece: 👉 El sistema necesita una manera de saber qué datos pertenecen a cada archivo. 📚 El sistema de archivos funciona un poco como un índice Imagina tener un disco lleno de información sin ningún mecanismo para organizarla. Tendrías millones de bloques de datos, pero no sabrías: ¿Cuáles pertenecen a foto.jpg? ¿Cuáles pertenecen a documento.pdf? ¿Cuáles están libres? ¿Cuáles forman parte del sistema? El sistema de archivos proporciona esa organización. Simplificando muchísimo: Archivo ↓ Sistema de archivos ↓ Referencia a bloques ↓ Datos físicos Cuando abres una fotografía, el sistema utiliza esa información para localizar las partes correspondientes y presentarlas como un único archivo. Por eso eliminar un archivo no necesariamente necesita comenzar destruyendo cada uno de sus bits. Puede empezar simplemente modificando esas referencias. ⚙️ ¿Qué ocurre cuando presionas “Eliminar”? Muchas veces existe primero una etapa intermedia. En sistemas de escritorio, cuando envías un archivo a la papelera, normalmente el archivo todavía sigue existiendo. Simplemente fue movido o marcado de manera que aparezca dentro de la papelera. Por eso puedes restaurarlo fácilmente. El flujo podría verse así: vacaciones.jpg ↓ 🗑️ Papelera ↓ Restaurar En este punto todavía no hablamos necesariamente de una eliminación definitiva. Cuando vacías la papelera o utilizas una eliminación que la omite, entonces el sistema puede marcar el archivo como eliminado. Pero incluso ahí no significa necesariamente: sobrescribir todos los datos con ceros inmediatamente 🧩 Muchas veces borrar significa liberar espacio lógico Supongamos que un archivo ocupa determinados bloques. Antes: Bloque 100 → vacaciones.jpg Bloque 101 → vacaciones.jpg Bloque 102 → vacaciones.jpg Después de eliminarlo, el sistema podría pasar a considerar: Bloque 100 → disponible Bloque 101 → disponible Bloque 102 → disponible La diferencia importante es esta: ANTES espacio perteneciente al archivo DESPUÉS espacio disponible para reutilización No necesariamente hubo que destruir en ese instante el contenido anterior. El sistema simplemente deja de considerar esos bloques como parte de un archivo válido. 🚀 Una analogía sencilla: una biblioteca Imagina una biblioteca enorme. En su catálogo aparece: Libro A → Estante 47 Cuando alguien solicita el libro, el bibliotecario consulta el catálogo y sabe exactamente dónde encontrarlo. Ahora imagina que decides eliminarlo del inventario. Podrías hacer: Eliminar: Libro A → Estante 47 y marcar: Estante 47 → disponible Desde el punto de vista administrativo: Libro A ya no existe. Pero físicamente el libro podría continuar ahí. Simplemente nadie debería buscarlo utilizando el catálogo. Algún tiempo después alguien coloca: Libro B en ese mismo estante. Ahora el contenido anterior sí fue reemplazado. Borrar archivos puede parecerse conceptualmente a esto en determinados sistemas. 🔎 ¿Entonces por qué existen programas para recuperar archivos borrados? Precisamente porque a veces existe una diferencia entre: El archivo dejó de estar registrado. y: Los datos fueron físicamente reemplazados. Si todavía existe suficiente información en el almacenamiento, una herramienta de recuperación puede intentar encontrarla. Hay varias posibilidades. Podría recuperar información sobre el archivo que todavía permanezca en estructuras del sistema de archivos. O podría buscar directamente patrones conocidos dentro de los datos. Por ejemplo, determinados formatos tienen estructuras identificables. Una herramienta puede buscar firmas que indiquen: Aquí probablemente comienza un JPEG. y tratar de reconstruir el contenido. 🧩 Recuperar el nombre y recuperar los datos no son exactamente lo mismo Imagina que eliminaste: vacaciones-cancun-2026.jpg Puede ocurrir que los datos de la imagen todavía estén presentes, pero la información original sobre: nombre ruta fecha ya no esté completamente disponible. Una herramienta podría recuperar entonces algo como: file000237.jpg El contenido sobrevivió. Pero parte de los metadatos utilizados para identificarlo se perdió. Por eso una recuperación puede producir archivos aparentemente completos con nombres completamente diferentes. 🧱 ¿Qué pasa si el archivo estaba fragmentado? Otro problema aparece cuando un archivo no estaba almacenado de manera completamente contigua. Imagina: vacaciones.jpg parte 1 → bloque 100 parte 2 → bloque 500 parte 3 → bloque 900 El sistema de archivos sabe cómo relacionar esas partes. Pero después de una eliminación, algunas de esas referencias podrían perderse. Una herramienta de recuperación necesitaría reconstruir correctamente: parte 1 + parte 2 + parte 3 Si una de ellas ya fue sobrescrita: parte 1 ✅ parte 2 ❌ parte 3 ✅ el archivo podría recuperarse parcialmente o quedar corrupto. Por eso recuperar un archivo eliminado no siempre significa obtenerlo exactamente como estaba. ⚠️ Por eso debes dejar de utilizar la unidad si borraste algo importante Supongamos que eliminaste accidentalmente un documento. El sistema ahora considera sus bloques: disponibles Después instalas un programa. Descargas videos. Copias fotografías. Actualizas el sistema. Cada una de esas acciones puede generar escrituras. El almacenamiento podría reutilizar justamente esos bloques. Conceptualmente: Documento eliminado ↓ espacio disponible ↓ descargas archivo nuevo ↓ parte del espacio se reutiliza ↓ datos antiguos sobrescritos Cuanto más escribes, mayores pueden ser las posibilidades de reemplazar información que todavía era recuperable. Por eso una recomendación habitual ante una eliminación accidental importante es: 👉 minimizar nuevas escrituras sobre esa unidad. 💿 En un disco duro tradicional, este modelo es relativamente intuitivo En un HDD, la información se almacena magnéticamente sobre platos. Simplificando mucho, el sistema puede marcar determinados sectores como disponibles sin necesidad de sobrescribirlos inmediatamente. Mientras esos sectores no sean reutilizados, parte de la información anterior puede permanecer. Por eso históricamente ha sido posible recuperar archivos eliminados de discos duros incluso después de vaciar la papelera. Pero esto no significa que la recuperación esté garantizada. Depende de: Cuánto tiempo pasó. Cuánto se utilizó el disco. Qué partes fueron sobrescritas. Qué información del sistema de archivos sobrevivió. El estado físico del dispositivo. ⚡ En un SSD la historia cambia bastante Los SSD no funcionan como discos duros. No tienen platos magnéticos ni cabezales. Utilizan memoria flash y un controlador que administra internamente dónde colocar la información. Y ahí aparece un mecanismo importante: TRIM . 🧠 ¿Qué es TRIM? Cuando eliminas un archivo, el sistema operativo sabe que determinados bloques lógicos ya no contienen información que necesites conservar. Pero el SSD también necesita saberlo. TRIM permite comunicarle algo conceptualmente parecido a: Estos bloques ya no contienen información válida que necesite conservarse. El SSD puede utilizar esa información para preparar espacio para futuras escrituras. Este comportamiento puede mejorar el rendimiento y la gestión interna del dispositivo. Pero tiene una consecuencia importante: 👉 La recuperación de archivos eliminados puede resultar mucho más difícil. 🔄 Un SSD no necesariamente escribe donde tú imaginas Supongamos que desde el sistema operativo ves: Bloque lógico 100 No significa necesariamente que exista una relación simple y permanente con una única posición física de memoria. El controlador del SSD utiliza mecanismos internos para administrar las celdas. Puede hacer cosas como: Wear leveling. Garbage collection. Remapeo de bloques. Gestión de páginas. Movimiento interno de datos. Todo esto ocurre para utilizar mejor la memoria flash y prolongar su vida útil. Por eso pensar: “Voy a sobrescribir exactamente el mismo sector varias veces” no funciona en SSD de la misma manera intuitiva que podría imaginarse con un HDD. 🧹 ¿Qué es Garbage Collection en un SSD? La memoria flash tiene restricciones importantes. Generalmente no puede simplemente sobrescribir cualquier pequeño fragmento directamente de la misma manera que otros tipos de almacenamiento. Las operaciones de borrado se realizan en unidades mayores. Por eso el controlador necesita reorganizar internamente información válida y liberar bloques. Conceptualmente: Bloque ├── Datos válidos ├── Datos eliminados ├── Datos eliminados └── Datos válidos El SSD puede copiar los datos todavía válidos a otro lugar y liberar el bloque completo. Este proceso se relaciona con el garbage collection . Si los datos eliminados son tratados como innecesarios, eventualmente pueden dejar de existir físicamente sin que tú escribas directamente sobre ellos. ⚠️ Esto explica por qué recuperar desde SSD puede ser mucho más complicado En un HDD tradicional podrías tener: archivo eliminado ↓ sectores no sobrescritos ↓ posible recuperación En un SSD con TRIM activo podría ocurrir: archivo eliminado ↓ TRIM ↓ SSD sabe que esos datos ya no son necesarios ↓ garbage collection ↓ datos eliminados internamente El tiempo exacto y el comportamiento dependen del dispositivo, sistema operativo y configuración. Por eso no deberías asumir: “Como acabo de eliminarlo, todavía estará físicamente ahí.” Con almacenamiento moderno, eso puede dejar de ser cierto mucho antes de lo esperado. 🔐 El cifrado cambia todavía más el problema Imagina un dispositivo cuyo almacenamiento está completamente cifrado. Los datos físicos podrían existir como bloques cifrados. Para interpretarlos necesitas una clave. Eso permite otra estrategia interesante de eliminación segura: 👉 destruir las claves necesarias para descifrar los datos. Esto suele conocerse como crypto erase o borrado criptográfico. Conceptualmente: Datos cifrados + Clave = Información legible Si destruyes correctamente la clave: Datos cifrados + ❌ clave = información prácticamente inutilizable Esto puede ser mucho más rápido que intentar sobrescribir físicamente enormes cantidades de almacenamiento. 🛡️ Por eso el cifrado completo del disco es importante Imagina que alguien roba una computadora. Si el disco no está cifrado, dependiendo del sistema y de cómo se hayan eliminado archivos, podría existir información recuperable. Con cifrado completo correctamente configurado, el atacante primero necesita superar la protección criptográfica. Herramientas como: BitLocker FileVault LUKS son ejemplos de tecnologías utilizadas para cifrar almacenamiento en diferentes sistemas. El cifrado no sustituye buenas políticas de seguridad, pero cambia radicalmente el riesgo asociado a datos residuales. 🗑️ “Eliminar” y “eliminar de forma segura” son operaciones diferentes Cuando utilizas el botón normal: Eliminar el objetivo principal suele ser: dejar de mostrar el archivo + recuperar su espacio Pero cuando necesitas eliminar información sensible, el objetivo cambia: hacer que recuperar los datos sea prácticamente inviable Son problemas diferentes. Por eso sistemas y dispositivos pueden ofrecer funciones especiales de borrado seguro. 🧹 ¿Sobrescribir muchas veces un archivo garantiza destruirlo? Existe una idea bastante popular: “Para eliminar algo de forma segura debes sobrescribirlo siete, diez o treinta veces.” En discos modernos esto suele ser una simplificación innecesaria. En discos magnéticos actuales, una sola sobrescritura adecuada suele ser suficiente para escenarios normales. Y en SSD existe un problema adicional: 👉 El controlador puede redirigir escrituras hacia celdas diferentes. Por ejemplo, tú podrías intentar: sobrescribir bloque lógico 100 pero internamente el SSD podría colocar esos nuevos datos en una ubicación física diferente por razones de wear leveling. Eso significa que una herramienta que intenta sobrescribir un archivo individual no necesariamente controla qué ocurre físicamente con cada copia anterior de esos datos. 🧰 ¿Qué usar entonces para borrar un SSD de forma segura? Depende del dispositivo, sistema operativo y nivel de seguridad requerido. Para eliminar completamente una unidad pueden existir opciones como: Secure Erase proporcionado por el dispositivo. Sanitize commands. Funciones del fabricante. Borrado criptográfico. Restablecimientos seguros. Herramientas específicas del sistema. No existe un comando universal que sea correcto para todos los SSD. En entornos donde la información es especialmente sensible, también pueden existir procedimientos de destrucción física. La estrategia debe corresponder al riesgo. ☁️ ¿Y qué ocurre con archivos almacenados en la nube? La situación se vuelve todavía más interesante. Cuando borras algo de un servicio en la nube, puede existir: Archivo visible ↓ Papelera ↓ Eliminación lógica ↓ Sistemas internos ↓ Replicación ↓ Backups No significa necesariamente que todos los bytes desaparezcan instantáneamente de cada dispositivo físico del proveedor. Los servicios suelen tener políticas de retención, replicación, respaldos y eliminación. Por eso debes distinguir entre: Ya no accesible para el usuario y: eliminado definitivamente de toda infraestructura El segundo proceso puede depender de políticas internas y periodos de retención. 📱 También ocurre en teléfonos Cuando borras una fotografía en un smartphone muchas veces sucede primero: Foto ↓ Eliminados recientemente ↓ 30 días ↓ eliminación Mientras se encuentra en esa sección, recuperarla puede ser trivial. Después de eliminarla definitivamente, la posibilidad de recuperación dependerá del almacenamiento, cifrado, TRIM y comportamiento interno del dispositivo. Los smartphones modernos utilizan almacenamiento flash, por lo que las ideas de un viejo disco duro no siempre se aplican directamente. 🧩 El sistema de archivos también puede conservar información adicional Algunos sistemas utilizan mecanismos como: Journaling. Snapshots. Versiones. Copias de seguridad. Esto significa que eliminar un archivo de su ubicación principal no siempre implica que ninguna otra copia exista. Por ejemplo, podrías borrar: /documentos/reporte.pdf pero conservar una versión dentro de: snapshot de ayer Esto es muy útil para recuperación. Pero también importa cuando tu objetivo es destruir información sensible. Eliminar la copia principal no necesariamente elimina todas las versiones históricas. 📸 ¿Por qué a veces una recuperación encuentra miniaturas aunque no encuentre la fotografía? Muchos sistemas y aplicaciones generan archivos derivados. Por ejemplo: foto-original.jpg ↓ miniatura ↓ preview ↓ cache Puedes eliminar el archivo original pero continuar teniendo una miniatura guardada en otra ubicación. Eso significa que una herramienta forense podría encontrar: preview pequeño ✅ archivo original ❌ La información puede haber dejado rastros en diferentes lugares. Por eso la eliminación segura de información sensible puede ser bastante más compleja que borrar un único archivo. 🔍 Recuperación normal vs análisis forense También conviene separar dos conceptos. Una herramienta doméstica de recuperación puede buscar archivos borrados relativamente recientes. Un análisis forense profesional puede intentar reconstruir mucha más información utilizando: Estructuras del sistema de archivos. Fragmentos. Metadatos. Cachés. Snapshots. Logs. Copias temporales. Eso no significa que todo archivo eliminado sea recuperable. Pero sí demuestra que: 👉 “No aparece en el explorador” no equivale automáticamente a “no queda ningún rastro”. ⚠️ Error común: instalar el programa de recuperación en el mismo disco Imagina que eliminaste accidentalmente: tesis.docx y enseguida descargas un programa de recuperación de 500 MB al mismo disco. Acabas de generar nuevas escrituras. Incluso la instalación puede crear: archivos cachés logs temporales y alguno de ellos puede reutilizar espacio donde estaba la tesis. Cuando el archivo es realmente importante, lo ideal suele ser reducir al mínimo cualquier escritura sobre la unidad afectada y trabajar desde otra unidad o entorno cuando sea posible. ⚠️ Tampoco conviene ejecutar reparaciones sin entender qué hacen Si una unidad parece dañada y contiene información importante, ejecutar inmediatamente herramientas que modifiquen el sistema de archivos puede cambiar estructuras necesarias para recuperación. En casos críticos: datos importantes + fallo físico o corrupción puede ser preferible trabajar primero sobre una copia o imagen del dispositivo. Especialmente si el disco hace ruidos, desaparece o presenta fallos físicos, seguir utilizándolo puede empeorar la situación. 🛠️ Buenas prácticas si borraste accidentalmente algo importante De forma general: ✔️ Deja de utilizar la unidad tanto como sea posible. ✔️ Evita copiar archivos nuevos allí. ✔️ No instales herramientas de recuperación en esa misma unidad. ✔️ Comprueba primero papelera, backups, snapshots y servicios de nube. ✔️ Si el dispositivo está fallando físicamente, evita pruebas destructivas. ✔️ Si los datos son realmente críticos, considera recuperación profesional. Y, sobre todo: 👉 No dependas de la recuperación como estrategia de respaldo. 💾 La mejor recuperación sigue siendo tener un backup Los programas de recuperación existen porque las cosas salen mal. Pero confiar en ellos es apostar a que los datos no hayan sido sobrescritos o eliminados definitivamente. Un backup evita esa incertidumbre. Conceptualmente: Archivo original ↓ eliminación accidental ❌ Backup ↓ restaurar ✅ Para archivos importantes, es mucho más seguro mantener copias independientes que esperar que una herramienta pueda reconstruir información eliminada. 🔐 Y si vas a vender o regalar un dispositivo, borrar tus carpetas no es suficiente Imagina que vas a vender una laptop. Haces: Seleccionar todo ↓ Eliminar ↓ Vaciar papelera Eso no debería considerarse automáticamente una sanitización segura del dispositivo. Una estrategia adecuada depende del almacenamiento y del sistema. En equipos modernos suele ser recomendable utilizar las funciones oficiales de restablecimiento seguro, borrado del dispositivo o herramientas proporcionadas para ese hardware, especialmente si la unidad estaba cifrada. El objetivo debería ser asegurarte de que el siguiente propietario no pueda acceder razonablemente a tu información anterior. 🧠 Hay tres niveles que conviene distinguir Podemos resumir el concepto con tres estados diferentes. 1. Archivo visible vacaciones.jpg ✅ El sistema sabe dónde está y puedes abrirlo. 2. Archivo eliminado vacaciones.jpg ❌ espacio reutilizable ✅ Ya no aparece normalmente, pero parte de sus datos podría continuar presente. 3. Datos destruidos o inaccesibles datos sobrescritos o bloques eliminados o clave criptográfica destruida En este punto recuperar la información puede ser inviable. La transición entre el segundo y el tercer estado depende mucho del tipo de almacenamiento. 🧩 La realidad Cuando presionas: Eliminar no necesariamente estás ordenando: “Encuentra cada bit de este archivo y destrúyelo físicamente ahora mismo.” Muchas veces estás diciendo algo mucho más parecido a: Este archivo ya no debe formar parte del sistema de archivos. El espacio que ocupaba puede reutilizarse. Después, lo que ocurra físicamente depende de múltiples capas: Sistema operativo ↓ Sistema de archivos ↓ Controlador ↓ Tipo de almacenamiento ↓ HDD / SSD / flash En un HDD, los datos pueden permanecer hasta que otros los sobrescriban. En un SSD, mecanismos como TRIM y garbage collection pueden hacer que desaparezcan de otra manera. Con cifrado, incluso puede ser suficiente destruir una clave para volver los datos inutilizables. Y si existen snapshots, backups o cachés, podrían sobrevivir copias adicionales. Por eso “borrar” no es una única operación universal. 💬 En almacenamiento, “ya no puedo verlo” y “los datos dejaron de existir” son dos afirmaciones completamente diferentes. 👉 ¿Alguna vez eliminaste accidentalmente una fotografía o documento y lograste recuperarlo después de vaciar la papelera? 🔥 El backend no se ve, pero sin él, nada funciona.
🌿 Tienes una rama con varios días de trabajo y necesitas integrarla al proyecto Tu compañero te dice: Haz merge. Otro desarrollador responde: Mejor haz rebase. Los dos caminos pueden terminar llevando tus cambios hacia la rama principal. Pero no hacen exactamente lo mismo. Y, sobre todo, no dejan la misma historia. Entonces aparece una pregunta bastante común cuando empiezas a trabajar seriamente con Git: 👉 ¿Qué diferencia realmente a git merge de git rebase ? 🧠 Partamos de dos ramas Imagina este historial: A — B — C ← main \ D — E ← feature La rama feature nació desde B . Mientras trabajabas en ella, main recibió el commit C . Ahora quieres integrar ambos trabajos. Tienes al menos dos estrategias muy conocidas: git merge o git rebase El resultado final puede contener cambios equivalentes, pero la forma en que Git registra la historia será distinta. 🔀 Opción 1: git merge Con merge , Git conserva ambas líneas de desarrollo y crea un punto donde se unen. Podrías hacer: git switch main git merge feature Y terminar con algo parecido a: A — B — C —— M \ / D — E M es un merge commit. Ese commit tiene dos padres: C E y representa explícitamente el momento en que ambas ramas se combinaron. Git no necesita fingir que la rama feature nunca se separó. Al contrario. La historia muestra claramente: main avanzó por un lado feature avanzó por otro y después se integraron 📖 Merge conserva la historia tal como ocurrió Esta es una de las mayores características de merge . Los commits: D E siguen siendo exactamente los mismos commits. No cambian sus identificadores. La historia conserva la bifurcación original. Conceptualmente: B ├── C └── D — E ↓ merge Esto puede ser útil cuando quieres entender: Cuándo se creó una rama. Qué commits pertenecían a una funcionalidad. En qué momento se integró. Qué líneas de desarrollo existieron en paralelo. El historial puede ser más ramificado, pero también más fiel a lo ocurrido. ⚡ ¿Siempre se crea un merge commit? No. Git también puede hacer un fast-forward merge . Imagina este caso: A — B ← main \ C — D ← feature Si main no avanzó desde que creaste feature , no hay dos historias que realmente necesiten fusionarse. Git puede simplemente mover el puntero de main : A — B — C — D ↑ main Eso se conoce como fast-forward . Puedes incluso forzar la creación de un merge commit usando opciones como: git merge --no-ff feature si el equipo quiere conservar explícitamente el hecho de que existió una rama. 🧹 Opción 2: git rebase rebase funciona de otra manera. En lugar de unir dos historias conservando la bifurcación, toma los commits de tu rama y los vuelve a aplicar sobre otra base. Partimos de: A — B — C ← main \ D — E ← feature Desde feature podrías ejecutar: git rebase main Git conceptualmente hace algo parecido a: 1. Identifica D y E 2. Los separa temporalmente 3. Mueve feature encima de C 4. Reaplica los cambios de D 5. Reaplica los cambios de E El resultado sería: A — B — C — D' — E' Ahora parece que el trabajo de feature comenzó después de C . El historial queda lineal. ⚠️ D' y E' no son los mismos commits Este punto es fundamental. Aunque: D' pueda contener prácticamente los mismos cambios que: D Git los considera commits diferentes. ¿Por qué? Porque el identificador de un commit depende de información como: Su contenido. Su padre. Sus metadatos. El árbol asociado. Antes: D → padre B Después del rebase: D' → padre C Cambió el padre. Por lo tanto cambia también el hash. Lo mismo ocurre con los commits siguientes. Por eso decimos que rebase : 👉 reescribe la historia . 🧬 ¿Por qué el hash cambia? En Git un commit no es simplemente: "estos archivos cambiaron" También forma parte de una cadena histórica. Podemos imaginarlo así: Commit E ↓ apunta a D ↓ apunta a B Si cambias la base: E' ↓ apunta a D' ↓ apunta a C ya no estás hablando de la misma cadena de commits. Aunque el código final sea equivalente, la historia es diferente. 🔀 Merge une historias; Rebase mueve historia Una forma sencilla de recordarlo es: MERGE Conserva: A — B — C \ D — E y las une. Mientras que: REBASE Toma: D — E y los vuelve a colocar después de: C Por eso ambos sirven para integrar trabajo, pero lo hacen con filosofías distintas. ⚔️ Entonces… ¿cuál es mejor? No existe una respuesta universal. Depende del flujo de trabajo del equipo. merge Tiene ventajas como: ✔️ Conserva commits existentes. ✔️ No reescribe historia. ✔️ Es más seguro con ramas compartidas. ✔️ Muestra claramente cuándo se integraron líneas de desarrollo. Pero también puede producir un historial más complejo: * Merge feature-x |\ | * commit 3 | * commit 2 | * commit 1 * | |/ * otro commit Si existen muchas ramas y muchos merges, leer git log puede ser más difícil. 🧹 Rebase puede hacer la historia más sencilla de leer Después de rebase puedes obtener: A — B — C — D' — E' En lugar de: A — B — C —— M \ / D — E Esto puede facilitar cosas como: git log --oneline porque los commits aparecen en una secuencia más lineal. También puede hacer más sencillo revisar cómo evolucionó una funcionalidad. Pero ese beneficio tiene un precio: 👉 estás creando nuevos commits. ⚠️ La regla más importante de Rebase Hay una regla práctica muy conocida: Evita hacer rebase de commits públicos que otras personas ya están utilizando. ¿Por qué? Supongamos que publicas: D — E Tu compañero descarga esos commits. Ahora tú haces: git rebase main y terminas con: D' — E' Tu historial ahora dice: A — B — C — D' — E' Pero tu compañero todavía tiene: A — B \ D — E Desde la perspectiva de Git: D != D' E != E' Aunque representen trabajo parecido. Ahora existen dos versiones distintas de la misma historia. 💥 ¿Qué ocurre cuando intentas hacer push? Después de un rebase, es común que un push normal sea rechazado. Por ejemplo: git push puede fallar porque el historial remoto contiene: D — E mientras tú ahora tienes: D' — E' Git no puede simplemente avanzar la rama. Para reemplazar el historial remoto tendrías que hacer un push forzado. Muchas veces se recomienda: git push --force-with-lease en lugar de: git push --force porque --force-with-lease intenta protegerte de sobrescribir cambios remotos que no esperabas. Aun así, sigue siendo una operación que debe utilizarse con cuidado. 🚨 ¿Por qué git push --force puede ser peligroso? Imagina que tu rama remota tiene: D — E — F Tu compañero agregó F . Pero tú solamente conoces: D — E Después haces rebase: D' — E' y ejecutas: git push --force Podrías terminar reemplazando: D — E — F por: D' — E' El commit F desaparece de la referencia remota. Por eso --force-with-lease suele ser una opción más prudente. Antes de sobrescribir, comprueba que el remoto siga en el estado que esperabas. 🏡 Rebase suele ser mucho más cómodo en ramas privadas Supongamos que creaste: feature/login y solamente tú estás trabajando allí. Puedes tener commits como: WIP fix otro fix cambio rápido Mientras tanto main avanza. Antes de abrir tu Pull Request puedes hacer: git fetch origin git rebase origin/main Ahora tu trabajo queda encima de los cambios más recientes. Si nadie más depende de esos commits, reescribirlos es mucho menos problemático. Por eso una regla práctica común es: Historia local o privada → rebase puede ser cómodo. Historia pública y compartida → mucho más cuidado. No es una ley absoluta, pero ayuda bastante. 🔄 ¿Qué sucede cuando hay conflictos? Tanto merge como rebase pueden producir conflictos. Supongamos que main cambió: const timeout = 5000; Mientras tu rama cambió la misma línea: const timeout = 10000; Git no puede decidir automáticamente qué versión debería sobrevivir. Con merge , podría detenerse y pedirte resolver el conflicto antes de crear el merge commit. Con rebase , Git puede detenerse mientras reaplica uno de tus commits. El flujo típico sería: git rebase main Git detecta conflicto. Lo resuelves. Después: git add archivo.js git rebase --continue Si quieres cancelar todo: git rebase --abort y vuelves al estado anterior al rebase. 🧩 Una diferencia importante al resolver conflictos Con un merge normalmente resuelves el conflicto en el punto de integración. Conceptualmente: C \ M ← resolver diferencias / E Con rebase, Git reaplica tus commits uno por uno. Si tienes: D E F G podrías encontrar conflictos durante varios de esos commits. Eso puede ser útil porque Git te obliga a resolver la historia paso a paso. Pero también puede resultar más laborioso en ramas grandes. 🧠 Rebase también puede ser interactivo Existe una herramienta muy poderosa: git rebase -i o: git rebase --interactive Por ejemplo: git rebase -i HEAD~4 Git puede mostrar: pick a1b2c3 Crear componente pick d4e5f6 Corregir estilo pick g7h8i9 Fix pick j1k2l3 Otro fix Y puedes decidir: pick reword edit squash fixup drop Esto permite reorganizar commits antes de compartirlos. 🧹 ¿Para qué sirve squash ? Supongamos que tienes: Agregar login Corregir login Fix login Ahora sí funciona login Antes de integrar podrías convertir todo en: Agregar autenticación de usuarios Con rebase interactivo: pick A Agregar login squash B Corregir login squash C Fix login squash D Ahora sí funciona login Git combina esos commits. Esto puede producir una historia más fácil de entender. Pero nuevamente: 👉 estás reescribiendo commits. Por eso suele hacerse antes de que otras personas comiencen a depender de ellos. 🧾 ¿Qué es un historial “limpio”? Decir: “Rebase deja un historial limpio” puede ser demasiado subjetivo. Para algunos equipos, esto: A — B — C — D — E — F es limpio porque es lineal. Para otros equipos: A — B —— M \ / C-D es más informativo porque muestra cómo se desarrollaron las funcionalidades. La limpieza depende de qué información quieres conservar. Un historial extremadamente lineal puede ser fácil de leer. Un historial con merges puede explicar mejor la estructura real del trabajo. 🧭 ¿Qué estrategia utilizan los equipos? Hay muchísimas. Un equipo podría trabajar así: feature branch ↓ commits locales ↓ rebase sobre main ↓ Pull Request ↓ merge Otro: feature branch ↓ Pull Request ↓ merge commit Otro puede usar: squash merge y convertir todo el Pull Request en un único commit. Otro puede utilizar: rebase and merge desde plataformas como GitHub. No existe un único flujo correcto. Lo importante es comprender qué historia produce cada opción. 🔀 ¿Qué es Squash Merge? Muchas plataformas permiten integrar una rama tomando todos sus cambios y convirtiéndolos en un único commit. Supongamos: feature: D — E — F Al hacer squash merge podrías terminar en main con: A — B — C — S donde S contiene los cambios combinados de: D + E + F Esto produce un historial principal muy compacto. Puede ser útil cuando los commits internos de una Pull Request son solamente pasos temporales de desarrollo. 🧠 Merge commit vs Squash Merge vs Rebase Merge Podemos imaginar tres resultados distintos. Merge commit A — B — C —— M \ / D — E Conserva la estructura de la rama. Squash merge A — B — C — S Combina los cambios de la rama en un único commit. Rebase and merge A — B — C — D' — E' Reaplica cada commit linealmente sobre main . Los tres pueden producir un árbol de archivos final parecido. Pero la historia queda diferente. 🛠️ Una estrategia práctica para una rama personal Imagina que estás trabajando solo en: feature/productos Mientras desarrollas haces: Ajustar modelo Agregar endpoint Fix endpoint Agregar validación Fix validación Mientras tanto main recibe nuevos cambios. Podrías hacer: git fetch origin git rebase origin/main Resolver cualquier conflicto. Luego revisar: git log --oneline Y, si quieres, utilizar: git rebase -i para mejorar tus commits antes de abrir el Pull Request. Este uso de rebase suele ser bastante cómodo porque todavía controlas completamente esa historia. ⚠️ Una estrategia menos recomendable Imagina una rama: develop utilizada activamente por 15 desarrolladores. Todos hacen: git pull y crean trabajo desde ella. Hacer rebase de toda esa rama y forzar el historial remoto puede provocar bastante caos. Cada desarrollador tendrá referencias hacia los commits antiguos. Después tendrán que reconciliar sus ramas con los nuevos commits. No significa que sea imposible. Significa que el costo y el riesgo son mucho mayores. 🧠 ¿Y qué hace git pull ? Este punto también suele causar confusión. Cuando ejecutas: git pull Git normalmente combina dos operaciones: git fetch + integración Según tu configuración, esa integración puede realizarse mediante merge o rebase. Por ejemplo: git pull --rebase obtiene los cambios remotos y vuelve a aplicar tus commits locales encima. Supongamos: Remoto: A — B — C Local: A — B — D Con pull --rebase podrías terminar: A — B — C — D' en vez de crear un merge commit local. ⚙️ Puedes configurar el comportamiento de git pull Si un equipo prefiere rebase: git config pull.rebase true Si prefiere merge: git config pull.rebase false También existen otras configuraciones. Lo importante es saber qué está haciendo Git. Ejecutar comandos sin entender si están haciendo merge o rebase es una fuente común de historiales inesperados. 🧩 ¿Qué ocurre con git bisect y el debugging? El historial no sirve solamente para verse bonito. También es una herramienta de diagnóstico. Comandos como: git bisect permiten buscar qué commit introdujo un problema. Un historial con commits pequeños y coherentes puede facilitar mucho esa tarea. Por ejemplo: A ✅ B ✅ C ✅ D ❌ E ❌ Git puede ayudarte a identificar: D como el posible commit problemático. Por eso, ya sea que uses merge o rebase, vale la pena pensar en la calidad de los commits. Un historial lineal lleno de: fix fix2 ahora sí final final-final no necesariamente es mejor que un historial con ramas bien organizadas. 🔍 ¿Qué es más fácil de revisar? Depende. Un historial lineal permite leer: Commit 1 ↓ Commit 2 ↓ Commit 3 ↓ Commit 4 sin saltos. Pero los merge commits pueden aportar contexto: Aquí se integró feature/pagos Aquí se integró feature/reportes Aquí se integró hotfix/login Algunos equipos prefieren usar merges para representar unidades de trabajo. Otros prefieren que main sea completamente lineal. Ambas decisiones pueden ser razonables. ⚠️ Error común: usar rebase solamente porque “se ve más profesional” Un historial bonito no compensa un equipo confundido. Antes de usar rebase deberías entender: ¿Qué commits voy a reescribir? ¿Ya están publicados? ¿Alguien más depende de ellos? ¿Tendré que hacer force push? ¿Estoy preparado para resolver conflictos? Si no conoces las respuestas, quizá merge sea una opción más segura. El objetivo no es utilizar el comando más sofisticado. Es conservar una historia comprensible sin poner en riesgo el trabajo compartido. ⚠️ Error común: pensar que Merge nunca genera problemas Merge tampoco es perfecto. Si creas constantemente commits como: Merge branch 'main' into feature Merge main Merge main otra vez Merge main nuevamente puedes terminar con un historial extremadamente ruidoso. Por eso algunos equipos prefieren actualizar ramas con rebase antes de abrir un Pull Request. Otros aceptan esos merges porque priorizan no reescribir historia. La estrategia depende de las convenciones. 🛠️ Una guía sencilla Si estás trabajando en una rama solamente tuya y quieres actualizarla con los últimos cambios: git fetch origin git rebase origin/main puede ser una opción cómoda. Si estás integrando una rama compartida y quieres preservar su historia: git merge puede ser más apropiado. Si necesitas convertir una Pull Request con muchos commits temporales en una sola unidad lógica: Squash merge puede resultar útil. Pero siempre revisa primero las reglas del proyecto. 🧪 Un ejemplo completo Partimos de: A — B — C ← main \ D — E ← feature Con merge Ejecutas: git switch main git merge feature Resultado: A — B — C —— M \ / D — E Los commits originales sobreviven. Con rebase Desde feature : git rebase main Resultado: A — B — C — D' — E' Después puedes integrar mediante fast-forward: git switch main git merge feature Resultado final: A — B — C — D' — E' El código puede terminar prácticamente igual. La historia no. 🧩 La realidad git merge y git rebase no son simplemente dos comandos diferentes para hacer “lo mismo”. Ambos pueden integrar líneas de desarrollo, pero responden a preguntas distintas. merge dice: Estas ramas existieron por separado y aquí fue donde se unieron. rebase dice: Voy a tomar estos commits y volverlos a aplicar sobre una base más reciente. Uno conserva la topología original. El otro reorganiza parte de la historia. Y por eso elegir entre ambos no consiste únicamente en conseguir que el código compile. También estás decidiendo: 👉 ¿Cómo quieres que Git recuerde la evolución de tu proyecto? Un historial lineal puede ser muy cómodo. Un historial con merges puede conservar información valiosa. Lo importante es que el equipo entienda la estrategia y la aplique de forma consistente. 💬 Un historial limpio puede ayudar muchísimo, pero entender qué commits estás modificando es mucho más importante que hacer que el gráfico se vea bonito. 👉 En tus proyectos, ¿prefieres conservar explícitamente las ramas con merge o mantener main más lineal utilizando rebase ? 🔥 El backend no se ve, pero sin él, nada funciona.
Contacto
Escríbeme un mensaje por WhatsApp.
Mensaje rápido
Llena los campos y se abrirá WhatsApp con un mensaje listo para enviar.