Tal como mencioné en el artículo ¿Qué es un repositorio git bare?, a fin de poder subir cambios (git push) hacia un repositorio git, es necesario que el remoto sea un repositorio bare (preferentemente en un servidor centralizado). Sin embargo en este artículo voy a demostrar que también es posible hacer push sobre una copia de trabajo (repositorio non-bare).

Supongamos que tenemos un servidor donde hemos creado un repositorio git:

# cd /usr/local/git/
# git init vmware.git
# chown -R git:git vmware.git/
# chmod -R o-wrx vmware.git/

Sin embargo, deseamos trabajar sobre una copia local del mismo. Con lo cual hemos clonado el repositorio vía SSH, desde nuestra máquina local:

emi@hal9000:~/git_repos % git clone ssh://git@git.linuxito.com:2222/usr/local/git/vmware.git
Cloning into 'vmware'...
git@git.linuxito.com's password:
warning: You appear to have cloned an empty repository.

Luego, hemos agregado un archivo y creado nuestro primer commit:

emi@hal9000:~/git_repos % cp /usr/local/pyvmomi-community-samples/samples/list_datastore_space.py vmware/
emi@hal9000:~/git_repos % cd vmware/
emi@hal9000:~/git_repos/vmware % git add list_datastore_space.py 
emi@hal9000:~/git_repos/vmware % git commit -m "primer commit"
[master (root-commit) 15a6b74] primer commit
 1 file changed, 137 insertions(+)
 create mode 100755 list_datastore_space.py

El problema ocurre al momento de hacer push (enviar los cambios al repositorio remoto), y se observa el siguiente error:

emi@hal9000:~/git_repos/vmware % git push origin master
git@git.linuxito.com's password: 
Counting objects: 3, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 1.66 KiB | 1.66 MiB/s, done.
Total 3 (delta 0), reused 0 (delta 0)
remote: error: refusing to update checked out branch: refs/heads/master
remote: error: By default, updating the current branch in a non-bare repository
remote: is denied, because it will make the index and work tree inconsistent
remote: with what you pushed, and will require 'git reset --hard' to match
remote: the work tree to HEAD.
remote: 
remote: You can set 'receive.denyCurrentBranch' configuration variable to
remote: 'ignore' or 'warn' in the remote repository to allow pushing into
remote: its current branch; however, this is not recommended unless you
remote: arranged to update its work tree to match what you pushed in some
remote: other way.
remote: 
remote: To squelch this message and still keep the default behaviour, set
remote: 'receive.denyCurrentBranch' configuration variable to 'refuse'.
To ssh://git.linuxito.com:2222/usr/local/git/vmware.git
 ! [remote rejected] master -> master (branch is currently checked out)
error: failed to push some refs to 'ssh://git@git.linuxito.com:2222/usr/local/git/vmware.git'

Esto se debe a que, por defecto en git, no se permite actualizar la rama actual en un repositorio non-bare, ya que el árbol e índice quedan inconsistentes con lo que se ha enviado. De esta forma se requiere ejecutar git reset --hard para que el work tree actual coincida con HEAD (referencia al último commit en la rama actual).

Sin embargo, a partir de la versión 2.3.0 de git, es posible modificar este comportamiento para que se permita enviar cambios a un repositorio non-bare, a través de la opción "updateInstead" en la directiva de configuración receive.denyCurrentBranch.

Esta opción actualiza el directorio de trabajo (debe estar limpio) si se actualiza la rama actual. Así se permite sincronizar copias de trabajo.

Para configurar esta opción, es necesario ejecutar los siguientes comandos en el servidor remoto:

# cd /usr/local/git/vmware.git/
# git config --local receive.denyCurrentBranch updateInstead
# chown git:git .git/config

Luego desde la copia local es posible hacer el push:

emi@hal9000:~/git_repos/vmware % git push origin master
git@git.linuxito.com's password: 
Counting objects: 3, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 1.66 KiB | 1.66 MiB/s, done.
Total 3 (delta 0), reused 0 (delta 0)
To ssh://git.linuxito.com:2222/usr/local/git/vmware.git
 * [new branch]      master -> master

Es posible comprobar que las ramas en ambos repositorios coinciden:

emi@hal9000:~/git_repos/vmware % git show-ref --head
8e00953bdeece48c3937f833963e69745cc3b8a5 HEAD
8e00953bdeece48c3937f833963e69745cc3b8a5 refs/heads/master
8e00953bdeece48c3937f833963e69745cc3b8a5 refs/remotes/origin/master
root@git:/usr/local/git/vmware.git# git show-ref --head
8e00953bdeece48c3937f833963e69745cc3b8a5 HEAD
8e00953bdeece48c3937f833963e69745cc3b8a5 refs/heads/master

Referencias


Tal vez pueda interesarte


Compartí este artículo