Comment pousser vers un référentiel Git non nu?

150

Je travaille généralement sur un serveur distant via ssh (screen et vim), où j'ai un référentiel Git. Parfois, je ne suis pas en ligne, donc j'ai un référentiel séparé (cloné depuis ma télécommande) sur mon ordinateur portable.

Cependant, je ne peux pas extraire de ce référentiel du côté distant car je suis généralement derrière un pare-feu ou je n'ai pas d'adresse IP publique.

J'ai lu que je devrais pousser juste vers un référentiel nu. Comment dois-je ensuite envoyer mes modifications dans mon référentiel distant?

woky
la source
3
avoir 2 dépôts distants, un nu et un normal, et utiliser des crochets. semble être un problème, mais selon git ready et le wiki officiel de git , vous ne devriez pousser que vers un dépôt nu . c'est probablement pourquoi la plupart des hôtes git repo (par exemple GitHub, Bitbucket) incluent des hooks de post-réception, vous pouvez donc POSTER sur une URL sur votre serveur qui exécute un script qui s'exécute par exemple git pull github master.
Jake Berger

Réponses:

137

receive.denyCurrentBranch updateInstead

Cette option a été ajoutée dans Git 2.3 et permet au serveur de mettre à jour son arbre de travail s'il est propre.

Donc, si vous vous assurez de toujours vous engager avant de tirer localement et de conserver une arborescence de travail propre sur le serveur (ce que vous devriez faire pour éviter les conflits de fusion), cette option est une bonne solution.

Exemple d'utilisation:

git init server
cd server
touch a
git add .
git commit -m 0
git config --local receive.denyCurrentBranch updateInstead

cd ..
git clone server local
cd local
touch b
git add .
git commit -m 1
git push origin master:master

cd ../server
ls

Production:

a
b
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
la source
est-il possible de pousser sans créer un repo nu comme le fait Heroku
ANinJa
2
@ANinJa Je ne comprends pas, n'est-ce pas exactement ce que fait mon exemple?
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
est --localfacultatif?
Yukulélé
@ Yukulélé --localn'affecte que le répertoire courant, --globalaffecte tous les dépôts git avec ~/.gitconfig, voir man git-config.
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
1
merci @CiroSantilli 新疆 改造 中心 六四 事件 法轮功 après avoir lu la doc je confirme que ce n'est pas nécessaire "(vous pouvez dire --local mais c'est la valeur par défaut)"
Yukulélé
146

Meilleure option

Le moyen le plus propre, le moins déroutant et le plus sûr de pousser dans votre référentiel distant non nu est probablement de pousser vers des branches dédiées dans la télécommande qui représentent les branches de votre ordinateur portable.

Examinons le cas le plus simple et supposons que vous n'avez qu'une seule branche dans chaque dépôt: master. Lorsque vous poussez vers le référentiel distant depuis votre ordinateur portable, au lieu de pousser master -> master, push master -> laptop-master (ou un nom similaire). De cette façon, le push n'affecte pas la branche principale actuellement extraite dans le référentiel distant. Pour ce faire depuis l'ordinateur portable, la commande est assez simple:

git push origin master:laptop-master

Cela signifie que la branche maître locale sera poussée vers la branche nommée "laptop-master" dans le référentiel distant. Dans votre dépôt distant, vous aurez une nouvelle branche nommée "laptop-master" que vous pourrez ensuite fusionner dans votre remote master lorsque vous serez prêt.

Option alternative

Il est également possible de simplement pousser master -> master, mais pousser vers la branche actuellement extraite d'un dépôt non nu n'est généralement pas recommandé, car cela peut être déroutant si vous ne comprenez pas ce qui se passe. En effet, le fait de pousser vers une branche extraite ne met pas à jour l'arborescence de travail, donc vérifiergit status de la branche extraite qui a été poussée montrera exactement les différences opposées à ce qui a été le plus récemment poussé. Cela deviendrait particulièrement déroutant si l'arbre de travail était sale avant la poussée, ce qui est une grande raison pour laquelle cela n'est pas recommandé.

Si vous voulez essayer de pousser simplement master -> master, alors la commande est juste:

git push origin

Mais lorsque vous revenez au référentiel distant, vous voudrez probablement faire une git reset --hard HEADpour synchroniser l'arborescence de travail avec le contenu qui a été poussé. Cela peut être dangereux , car s'il y a des modifications non validées dans l'arborescence de travail à distance que vous vouliez conserver, elles les effaceront. Assurez-vous de savoir quelles en sont les conséquences avant de l'essayer, ou du moins faites d'abord une sauvegarde!

EDIT Depuis Git 2.3, vous pouvez utiliser "push-to-deploy" git push: https://github.com/blog/1957-git-2-3-has-been-released . Mais pousser vers une branche distincte, puis fusionner est généralement préférable car il effectue une fusion réelle (fonctionne donc avec des modifications non validées, tout comme la fusion le fait).

Moulage Dan
la source
1
Est-il possible d'automatiser le branchement après avoir poussé le laptop-master?
rdoubleui
3
@rdoubleui: Vouliez-vous dire "automatiser la fusion "? Si tel est le cas, non, il n'est pas possible d'automatiser la fusion car il n'est pas garanti que les fusions soient possibles sans intervention humaine. Il peut y avoir des conflits qui doivent être résolus.
Dan Moulding
7
dans les versions ultérieures (?), git config receive.denyCurrentBranch ignoredoit être fait avant de pousser vers des
dépôts
3
Excellente réponse @DanMoulding, merci. @rdoubleui: vous pouvez toujours enregistrer une ligne de commande comme la suivante en tant que fonction bash:git push origin master:laptop-master && ssh user@remotemachine 'cd repos_path && git merge laptop-master'
Rich
@rdoubleui pour automatiser la fusion, vous pouvez utiliser gitolite et le configurer (un peu compliqué) pour rendre le commit non nu tout sale et le pousser sur la version gitolite (nue) en utilisant le déclencheur pré-git. Après cela, si la fusion ne peut pas être résolue dans le non-nu, elle rejettera votre poussée, vous savez donc que vous devez d'abord tirer, résoudre les fusions et pousser à nouveau. Je n'ai pas encore configuré cela, mais je suis en train de le faire et je pense que cela peut fonctionner.
17

Je suggérerais d'avoir un référentiel nu et un repos local (non nu) sur votre serveur. Vous pouvez transférer les modifications d'un ordinateur portable au référentiel nu de serveur, puis extraire de ce référentiel nu au référentiel de travail du serveur. La raison pour laquelle je dis cela est que vous pourriez avoir de nombreuses branches complètes / incomplètes sur le serveur que vous voudrez répliquer sur l'ordinateur portable.

De cette façon, vous n'avez pas à vous soucier de l'état de la branche extraite sur le référentiel de travail du serveur lors de la transmission des modifications au serveur.

Manish
la source
4

Une autre option consiste à configurer un tunnel SSH inversé afin que vous puissiez tirer au lieu de pousser.

# start the tunnel from the natted box you wish to pull from (local)
$ ssh -R 1234:localhost:22 user@remote

# on the other box (remote)
$ git remote add other-side ssh://user@localhost:1234/the/repo
$ git pull other-side

Et si vous voulez que le tunnel fonctionne en arrière-plan

$ ssh -fNnR 1234:localhost:22 user@remote
Todd libéré
la source
1

Tu peux faire:

$git config --bool core.bare true

cela peut être fait dans un référentiel nu ou central afin qu'il accepte tous les fichiers qui sont poussés à partir de référentiels non nus. Si vous faites cela dans un référentiel non nu, nous ne pouvons pas pousser de fichiers d'un référentiel non nu vers un référentiel nu.

Si vous pratiquez GIT en créant un repo central et non nu sur PC, il se peut qu'il ne montre pas les fichiers poussés dans certains PC, mais il a été poussé. vous pouvez le vérifier en exécutant.

$git log dans le repo central.

Sauf si vous poussez sur GitHub, les fichiers y seront affichés.

vidwan reddy
la source