SSD Nodes Learn 🎉 VPS desde $4.99/mes
Guías Matt ConnorPor Matt Connor

Git vs GitHub: diferencias para administrar un VPS

Git se ejecuta en su equipo o servidor; GitHub es un servicio alojado basado en Git y propiedad de Microsoft desde 2018. Conozca qué cambia en su VPS.

¿Qué es GitHub?

GitHub es un servicio alojado que almacena repositorios de Git y crea un sitio web alrededor de ellos. Git es el programa de control de versiones que se ejecuta en su propio equipo o servidor. GitHub es el producto de una empresa basado en Git y pertenece a Microsoft desde 2018. Puede usar Git todos los días sin abrir nunca GitHub. No puede usar GitHub sin Git.

Esta distinción importa desde el momento en que administra un VPS (servidor privado virtual). Git registra el historial de sus archivos de configuración y scripts de despliegue. GitHub conserva una copia de ese historial cuando el servidor no la tiene y también ofrece un lugar para ejecutar compilaciones y revisiones. Esta guía sigue un ejemplo desde una carpeta vacía hasta un despliegue en un servidor y define cada término nuevo cuando aparece por primera vez.

Qué hace Git por su cuenta

Git es un sistema de control de versiones. Registra el estado de un directorio a lo largo del tiempo para que pueda ver qué cambió, cuándo y por qué. Se escribió en 2005 para el desarrollo del kernel de Linux. Es distribuido, lo que significa que cada copia de un repositorio contiene todo el historial. El diseño no incluye un servidor central. El portátil de un compañero contiene una copia tan completa como la de cualquier servidor.

Instálelo y configure su identidad. Git no permite registrar un commit sin un nombre y una dirección de correo electrónico, porque ambos se escriben en el propio commit.

sudo apt update && sudo apt install -y git
git --version
git config --global user.name "Your Name"
git config --global user.email "you@example.com"

En Ubuntu 24.04, git --version muestra git version 2.43.0. Cualquier versión publicada en los últimos años se comporta igual con todo lo que se explica a continuación.

El ejemplo: un repositorio para los archivos de implementación de su VPS

Un repositorio, normalmente abreviado como «repo», es un directorio que Git supervisa. Se convierte en uno al ejecutar git init, que crea dentro un directorio oculto .git. Ese directorio es el repositorio. Elimine .git y quedará un directorio normal sin historial.

mkdir vps-deploy && cd vps-deploy
git init -b main
printf '.env\n*.key\n' > .gitignore

-b main asigna a la primera rama el nombre main. Si lo omite, Git muestra una indicación extensa sobre el nombre de la rama predeterminada. .gitignore enumera las rutas que Git nunca debe supervisar. Escriba el archivo de secretos en él desde el primer día, porque un archivo que se ha confirmado una vez permanece en el historial aunque lo elimine, y quitarlo correctamente implica reescribir cada confirmación posterior.

Commits: la unidad del historial

Ahora añada un script y regístrelo.

printf '#!/bin/sh\nsudo systemctl restart caddy\n' > restart.sh
git add restart.sh .gitignore
git commit -m "Add restart script and gitignore"
git log --oneline

git add mueve un cambio al área de preparación, que es la lista de elementos que se incluirán en el próximo commit. git commit escribe esa lista en el historial como una entrada. Un commit contiene una instantánea de cada archivo bajo seguimiento, un mensaje, un autor, una marca de tiempo y un puntero al commit anterior. git log --oneline muestra una línea por commit; cada línea comienza con un hash corto como a1b2c3d. Ese hash es el nombre del commit y casi todos los comandos de Git lo aceptan.

Omita el paso git add y git commit responde no changes added to commit (use "git add" and/or "git commit -a"). No hay ningún problema. Git indica que el área de preparación está vacía, por lo que no hay nada que incluir en la instantánea. git status es el comando que debe ejecutar cuando no sepa qué hacer: muestra el nombre de la rama actual, los cambios preparados y los archivos que Git puede ver pero que no están bajo seguimiento.

Ramas: una segunda línea de historial

Una rama es un puntero móvil a un commit. main es una rama y no tiene nada de especial en Git. Crear una rama no cuesta nada porque Git escribe un puntero nuevo en lugar de copiar los archivos.

git switch -c add-backup
printf '#!/bin/sh\nrestic backup /srv\n' > backup.sh
git add backup.sh
git commit -m "Add nightly backup"
git switch main
ls

Después de git switch main, backup.sh no aparece en el listado. No se ha eliminado nada. El archivo existe en la rama add-backup y main nunca lo tuvo, por lo que Git lo retiró del directorio de trabajo al cambiar de rama. Esto sorprende a todo el mundo una vez. git switch add-backup lo recupera.

Remotos: donde GitHub aparece por fin

Hasta ahora, todo se ejecutaba en una sola máquina y sin red. Un remoto es una URL con nombre que apunta a otra copia del mismo repositorio. GitHub aloja una de esas copias. El nombre convencional del remoto principal es origin.

Cree un repositorio vacío desde el sitio web de GitHub y conéctelo después. En este caso, prefiera SSH a HTTPS: una clave SSH es un archivo que usted controla y no caduca como un personal access token.

ssh-keygen -t ed25519 -C "vps-deploy"
cat ~/.ssh/id_ed25519.pub
ssh -T git@github.com

Pegue la clave pública mostrada en la página de claves SSH de su cuenta de GitHub y vuelva a ejecutar la prueba. Una clave operativa responde Hi yourname! You've successfully authenticated, but GitHub does not provide shell access.. GitHub no le proporciona un shell, por lo que ese rechazo indica que la autenticación se realizó correctamente. git@github.com: Permission denied (publickey). significa que nunca se ofreció la clave o que no se aceptó. Compruebe que pegó el archivo .pub y no la clave privada que está junto a él.

git remote add origin git@github.com:yourname/vps-deploy.git
git push -u origin main

git push envía sus commits al remoto. -u registra que el main local sigue al main remoto, por lo que más adelante basta con ejecutar git push sin argumentos. git clone <url> hace lo contrario en una máquina nueva: copia todo el repositorio con su historial y configura origin automáticamente. También puede usar un remoto HTTPS. Este funciona sobre el mismo protocolo que cualquier página web, lo que resulta útil en redes que bloquean el puerto saliente 22. Si necesita más detalles, qué contiene realmente una petición HTTP explica el funcionamiento.

Solicitudes de incorporación, incidencias y forks: las partes que son de GitHub, no de Git

Todo lo anterior es Git y funciona con cualquier servidor. Las tres palabras siguientes corresponden a funciones de GitHub. Otros servicios las copian, pero Git no sabe nada de ellas.

Una pull request (PR) es una solicitud para fusionar una rama con otra, presentada en una página para debatir los cambios. Haces push de add-backup, abres una PR contra main y el sitio muestra las diferencias commit a commit. Los usuarios comentan líneas concretas. Las comprobaciones automatizadas indican si pasan o fallan con respecto a la rama. Al hacer clic en merge, GitHub realiza la fusión en su propia copia y después actualiza main. El nombre procede del flujo de trabajo original, en el que se pedía a un mantenedor que hiciera pull de tu rama en la suya.

Una issue es un hilo numerado para un error o una tarea. Se almacena en la base de datos de GitHub, no en tu repositorio. Conviene saberlo antes de elegir un servicio: al clonar el repositorio obtienes todos los commits, pero ninguna issue. Para extraer las issues hay que llamar a la API.

Un fork es una copia del repositorio de otra persona en el servidor, asociada a tu cuenta. Tienes permisos de escritura sobre la copia, haces push de una rama y abres una pull request desde tu copia hacia la original. Así puedes contribuir a un proyecto cuyos mantenedores nunca han oído hablar de ti. Un fork es un clon que reside en GitHub y conserva la referencia a su origen.

El software lee los tres elementos mediante la misma API que utiliza una persona. Un agente de revisión de pull requests que ejecutas en tu propio servidor supervisa las PR nuevas, lee el diff y publica comentarios sobre líneas concretas. Existen convenciones como un archivo AGENTS.md en la raíz de un repositorio porque ahora las herramientas también leen los repositorios, además de las personas.

Qué hace realmente GitHub para el propietario de un VPS

Empiece por almacenar los datos fuera del servidor. Los scripts y playbooks de despliegue deben estar en un lugar distinto del servidor que configuran. Reconstruya el VPS desde una imagen nueva, clone y ejecute. Mantenga ese repositorio privado y asigne al servidor una deploy key: una clave SSH registrada para un solo repositorio en lugar de para toda la cuenta, configurada como de solo lectura. Si se filtra una deploy key de solo lectura, queda expuesto un único repositorio. Si se filtra una clave de cuenta, queda expuesto todo lo que pueda subir.

sudo git clone git@github.com:yourname/vps-deploy.git /srv/vps-deploy
cd /srv/vps-deploy
git pull --ff-only

--ff-only se niega a crear un commit de merge. En un servidor que solo consume cambios, un merge siempre es un accidente, por lo que esta opción convierte un historial confuso en el error claro fatal: Not possible to fast-forward, aborting.. Algo cambió en el servidor y no debería haber cambiado. Encuéntrelo antes de volver a hacer pull.

Si clona como root y después ejecuta Git con otro usuario, obtiene fatal: detected dubious ownership in repository at '/srv/vps-deploy'. Git se niega a leer un repositorio propiedad de otro usuario porque un .git/config malicioso puede hacer que Git ejecute comandos. Corrija la propiedad con chown en lugar de añadir una excepción safe.directory, ya que la excepción silencia la comprobación sin eliminar la causa.

GitHub Actions: canalizaciones de compilación y despliegue

Actions es el sistema de CI/CD (integración continua y entrega continua) de GitHub. Confirme un archivo YAML en .github/workflows/ y GitHub lo ejecutará cuando ocurra el evento que haya especificado.

name: check
on:
  push:
    branches: [main]
jobs:
  shellcheck:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v7
      - run: sudo apt-get update && sudo apt-get install -y shellcheck
      - run: shellcheck *.sh

El archivo es un flujo de trabajo. Un trabajo se ejecuta en una máquina. Un paso es un comando o una acción publicada. uses: incorpora una acción desde otro repositorio, y @v7 fija su versión principal (v7 es la actual para actions/checkout en agosto de 2026). Fije siempre una versión, porque una acción sin versión fijada ejecuta código que no ha revisado y que tiene acceso a sus secretos.

runs-on: ubuntu-latest solicita a GitHub una máquina virtual nueva, que se elimina cuando termina el trabajo. Los ejecutores estándar son gratuitos en los repositorios públicos, y el plan gratuito incluye 2,000 minutos al mes para los repositorios privados en agosto de 2026. Consulte la página de precios actual antes de elaborar un presupuesto basándose en esa cifra.

Los secretos se almacenan en la configuración del repositorio y se leen como ${{ secrets.DEPLOY_KEY }}. Un flujo de trabajo activado por una pull request desde un fork recibe un token de sólo lectura y no tiene acceso a esos secretos, porque de lo contrario un desconocido podría abrir una PR cuyo único objetivo fuera mostrarlos.

Ejecutar el runner de Actions en su propio VPS

runs-on: self-hosted envía el trabajo a una máquina que usted administra. La página de configuración del runner del repositorio proporciona una línea de descarga, la dirección web del repositorio y un token de registro válido durante una hora. Introduzca los dos últimos valores en REPO_URL y RUNNER_TOKEN. Después, la configuración requiere tres comandos.

./config.sh --url "$REPO_URL" --token "$RUNNER_TOKEN"
sudo ./svc.sh install
sudo ./svc.sh start
./svc.sh status

svc.sh status debería mostrar el servicio como activo y varias líneas recientes del registro. El runner abre una conexión HTTPS saliente con GitHub y solicita trabajo, por lo que no es necesario abrir ningún puerto entrante para él. svc.sh install escribe la unidad de systemd. Este es el paso que se suele omitir: sin él, el runner termina cuando se cierra la sesión SSH y todos los trabajos posteriores quedan en cola sin explicación. la configuración completa de un runner autoalojado en un VPS explica el endurecimiento y la limpieza necesarios para un runner de larga duración.

La ventaja es que una implementación ya no necesita una clave SSH entrante accesible desde Internet, porque el trabajo ya se ejecuta en el servidor. La caché de compilación también permanece disponible entre ejecuciones y no se factura ningún minuto.

Hay una advertencia que debe tenerse en cuenta. La documentación de GitHub recomienda usar runners autoalojados sólo con repositorios privados, porque las bifurcaciones de un repositorio público pueden ejecutar código peligroso en el runner al abrir una solicitud de incorporación de cambios. El runner ejecuta todo lo que indique el archivo de workflow de esa rama. En un repositorio privado donde usted controla quién puede hacer push, el riesgo es reducido. En un repositorio público, trate cualquier runner autoalojado como una máquina en la que personas desconocidas pueden ejecutar código.

¿Necesita realmente GitHub?

No. Git es el estándar y GitHub es una comodidad. Forgejo y Gitea son forjas autohospedadas; una forja es un servidor Git con incidencias y solicitudes de incorporación asociadas. Ambos se distribuyen como un único binario de Go y funcionan en un VPS pequeño. Forgejo es una bifurcación de Gitea de 2022 que ahora da servicio a Codeberg. Mover un repositorio requiere un solo comando porque el protocolo de red es idéntico.

git remote -v
git remote set-url origin git@git.example.com:you/vps-deploy.git
git push origin main

Cada commit se mueve porque cada clon ya contiene todo el historial. Lo que no se mueve es la capa que GitHub construyó encima: las incidencias y los hilos de las solicitudes de incorporación. CI tampoco se transfiere. Forgejo tiene su propia implementación de Actions, que lee YAML similar desde .forgejo/workflows/, y su documentación explica directamente las limitaciones: GitHub Actions y Forgejo Actions no son lo mismo y es posible que algunos elementos no funcionen de inmediato. También necesita su propio runner. Planifique ese paso como una migración, no como una copia.

La razón real por la que la mayoría de los proyectos permanece en GitHub son los colaboradores. El código público debe estar donde las personas ya tienen una cuenta. Sus scripts privados de despliegue no. Son dos decisiones distintas y puede responderlas de forma diferente.

Qué falla primero y qué indica el error

Se rechaza un push. Verá esto:

 ! [rejected]        main -> main (fetch first)
error: failed to push some refs to 'github.com:yourname/vps-deploy.git'
hint: Updates were rejected because the remote contains work that you do
hint: not have locally.

Se hizo un push desde su último pull. A menudo, se trata de una edición realizada en el editor web. Ejecute git pull --rebase para aplicar sus commits sobre los commits remotos y vuelva a hacer push. Evite git push --force en una rama compartida, porque elimina los demás commits de esa rama en el servidor.

fatal: refusing to merge unrelated histories. Ejecutó git init localmente y también permitió que GitHub creara el repositorio con un README. Los dos historiales no tienen ningún commit en común, por lo que Git no puede determinar cómo combinarlos. La solución más limpia es clonar la copia de GitHub en una carpeta nueva y mover allí sus archivos.

error: src refspec main does not match any. La rama indicada no existe aquí. Normalmente, el repositorio todavía no tiene ningún commit o la rama se llama master. git branch --show-current lo confirma.

Un secreto llegó a un commit. Rote la credencial de inmediato. Trátela como pública desde el momento en que se hizo el push, porque las bifurcaciones, los mirrors y las vistas en caché conservan copias que no puede eliminar.

FAQ

¿GitHub es lo mismo que Git?

No. Git es un programa de control de versiones que se instala en una máquina y funciona sin red ni cuenta. GitHub es un servicio comercial alojado que almacena repositorios de Git y añade una interfaz web, incidencias, pull requests y CI. Git se lanzó en 2005 y GitHub se lanzó en 2008 sobre esa base. Puede usar Git indefinidamente sin GitHub. Todas las funciones de GitHub dependen de Git.

¿Necesito una cuenta de GitHub para usar Git en mi VPS?

No. git init, git commit y git log funcionan en un servidor sin ningún remoto configurado, lo que ya basta para realizar el seguimiento de cambios en archivos /etc o scripts de despliegue. Una cuenta resulta útil cuando quiere una copia del historial que sobreviva al servidor o una segunda máquina desde la que clonarlo. Los servicios self-hosted como Forgejo y Gitea cubren la misma necesidad en hardware propio, y un remoto SSH simple que apunte a un repositorio bare en otro equipo funciona sin ningún software de forge.

¿Qué es un pull request?

Un pull request es una solicitud para fusionar una rama con otra, acompañada de una página de debate. Envía una rama, abre el PR contra main y el servicio muestra los cambios commit a commit para que los revisores puedan comentar líneas concretas y las comprobaciones automatizadas indiquen si se superan o fallan. Es una función de GitHub, no de Git, por lo que Git no tiene ningún comando para ello. Otros servicios implementan la misma idea y a veces la denominan merge request.

¿Debería ejecutar un runner de GitHub Actions en mi propio VPS?

Para un repositorio privado, a menudo sí. El trabajo se ejecuta en hardware que ya paga, no se contabilizan minutos, la caché de compilación permanece disponible y el despliegue ya no necesita exponer una clave SSH entrante a Internet, porque el runner se conecta de salida a GitHub y solicita trabajo. Para un repositorio público, GitHub lo desaconseja: cualquiera puede hacer fork del repositorio y abrir un pull request cuyo workflow ejecute código en su máquina.

¿Puedo trasladar mis repositorios fuera de GitHub más adelante?

El código, sí, fácilmente. Cada clon contiene el historial completo, por lo que git remote set-url origin <new url> seguido de un push mueve todo lo que contiene un commit. Lo que queda atrás es la capa que gestiona GitHub: las incidencias, los debates de los pull requests y el historial de Actions se almacenan en su base de datos, no en la carpeta .git. Las herramientas de migración pueden copiar las incidencias mediante la API, y los archivos de workflow normalmente necesitan modificaciones para adaptarlos a la CI del nuevo servicio. Tener esto presente es un argumento para guardar la documentación importante en el repositorio y no en los hilos de incidencias.

#github#git#version-control#ci-cd#developer-tools