Push impossible après un git rebase

Le problème exposé dans ce sujet a été résolu.

Hello,

Je teste la fonction rebase de git (grâce au tuto d'Eskimon) mais je suis face à un problème.

Voici ce que j'ai fait :

  1. initialiser un dépôt vide avec git init --bare --shared test.git
  2. cloner ce dépôt dans 2 endroits (un dans lequel je travaille et l'autre qui simule quelqu'un qui a aussi cloné le même dépôt, un collaborateur)
  3. J'ai fait 3 commits que j'ai pushé sans soucis, puis puller sur l'autre dépôt.
  4. J'ai fait un rebase (reword) pour renommer un message de commit.

Mais je n'arrive pas à pusher ces modifications, même avec git push -f. Personne d'autre n'a pushé dans ce dépôt depuis mon dernier commit.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
$ git push -f
Décompte des objets: 5, fait.
Delta compression using up to 4 threads.
Compression des objets: 100% (4/4), fait.
Écriture des objets: 100% (5/5), 514 bytes | 0 bytes/s, fait.
Total 5 (delta 2), reused 0 (delta 0)
remote: error: denying non-fast-forward refs/heads/master (you should pull first)
To ssh://example.com/srv/git/test.git
 ! [remote rejected] master -> master (non-fast-forward)
error: impossible de pousser des références vers 'ssh://example.com/srv/git/test.git'

J'ai raté quelque chose ?

Merci de ton aide. En effet c'est cela mais je pensais qu'il n'y avait pas besoin de changer la configuration par défaut pour autoriser cela.

Après recherche, il faut que denyNonFastforwards soit à false (par défaut à true) dans le fichier de configuration du serveur git. J'ai modifié et il a accepté mon push forcé :)

github doit accepté par défaut le denyNonFastforwards je suppose car je n'avais pas de problème avec github+rebase…

Dans certaines situations, il serait pertinent d'écraser l'ancien historique avec git push –force. C'est interdit en projet GL (via la variable de configuration receive.denyNonFastForwards), à la fois pour vous empêcher de commettre l'irréparable (effacer votre historique par erreur) et pour vous empêcher de tricher sur votre historique au moment des rendus. En dehors du projet, un git push –force est une bonne idée sur une branche qui n'a pas été intégrée (typiquement pour écraser une première version d'une pull-request avec une nouvelle version qui prend en compte des commentaires de relecteurs), mais pas sur la branche principale, sur laquelle d'autres développeurs peuvent avoir basé leur travail.

ensiwiki

NB: le rebase c'est dangereux et pas dans l'esprit de git. le merge c'est mieux.

Kje

Je vois pas bien pourquoi tu mets rebase et merge en parallèle. Ils n'ont pour moi (débutant) aucun rapport. L'un ne peut pas remplacer l'autre. Sinon dans quelle mesure ?

Si les deux permettent de mélanger deux branches. L'une en mixant les deux (le merge), l'autre en essayant de pousser les commits d'une branche à la suite d'une autre (le rebase).

Toujours est il que le rebase c'est dangereux. Si tu as des conflits dès les premiers commits c'est vite galère. De plus, objectivement, ça sert à rien. Beaucoups de gens font des commits pour tenter d'avoir un historique bien linéaire. C'est une erreur selon moi : l'objectif de git est justement de travailler sur plusieurs versions en parallèle. Un merge permet de conserver une information préciseuse : quels branches ont été développé en parallèles. En cas de soucis après le merge/rebase il est beaucoup plus facile de comprendre ce qui a put se passé apres un merge car l'historique montre toujours pour chaque commit l'état réel du code à ce moment là, et pas un truc fait automatiquement par git et qui ne correspond pas à la réalité du code du dev.

Bref rebase c'est le mal. Et le fait que tu sois obligé de faire un -f en est la preuve.

Le rebase distant est dangereux et c'est pourquoi le serveur ne l'autorise pas par defaut. Le rebase local avant de push me semble au contraire une bonne chose pour permettre d'avoir un historique au top.

Cela reste dangereux dans le sens ou si tu ne sais pas comment t'y prendre tu peux perdre ton travail local, mais cela ne l'est pas vis a vis du depot distant.

Même en local. J'ai du mal a voir l'interet de construire un historique linéaire alors que ce n'est pas ainsi qu'il a été codé. Le gros intéret des outils de versioning est de pouvoir revenir à n'importe quel version du code. En faisant un rebase tu perds ça et tu va avoir des commits intermédiaires qui ne correspondent pas aux vrais versions que tu as codé.

Avec un mode developpement en branches, je comprend pas l'interet de vouloir un historique linéaire. Le seul intéret que je vois au rebase c'est quand tu rebase sur le même commit d'origine pour venir regrouper certains commits consécutifs (si les versions intermédiaires n'ont pas d'intéret). Mais un rebase sur une autre branche non vraiment je ne comprend pas.

Je ne vois pas ce que les branches viennent faire dedans. J'utilise du rebasing sans toucher aux branches.

Quand je développe, je fais des petits commits à la con, avec des messages à la con, ce qui me permet de ne rien perdre de ce que je fais, et à la fin de les squash et leur met un titre plus explicite, notamment le tag de la tache sur laquelle je travaillais. Comme il m'arrive de travailler en parallèle sur plusieurs taches, au sein d'une même branche, j'ai aussi le besoin de réordonner, parfois corriger des erreurs (modifié des fichiers pour deux tâches et oubliés de commit pour l'une ou au moins d'utiliser un no-index par exemple), etc.

Et même, prenons l'exemple d'un workflow standard avec code reviewing. Tu as fini ta tâche, un ou quelques commits, et tu mets ça en review. Il se trouve qu'il y a des petites erreurs, de typo ou même que ta solution peut être un peu amélioré. Sur les conseils de tes collègues, tu fais quelques autres commits, souvent assez annexes. Avant de pusher, je rebase et squash les commits qui n'ont rien à faire tout seuls, réordonne les commits au besoin pour avoir une cohérence et que cela soit visible.

Je préfère largement avoir un unique commit "#ID - Implémentation de la feature X" puis "#ID - Corrections de la nomenclature et erreurs de typographies" plutôt que 25 commits "#ID - Oups, oublié tel fichier", "#ID - Renomme var en varBienPlusExplicite", etc.
C'est une question de ne pas noyer l'historique dans du bruit et pouvoir suivre au premier coup d'oeil ce qui se passe.

Et pourtant, que ce soit en utilisant des workflow en branches static ou feature branch, j'ai toujours eu besoin de rebase.

Personnellement, je me sers des deux. Je me sers des rebase interactif pour nettoyer mes commits (les split, les squash, les reword, …)… Et je me sers du rebase normal (avec ou sans -p) quand je veux mettre à jour ma branche par rapport à sa parente (exemple : un bug est corrigé dans la parente, j'en ai besoin => je rebase), plutôt qu'un merge dégueulasse qui justement entraine un peu (beaucoup) un concept d'oedipe : on ne sait plus qui est le parent, qui est l'enfant. Et je me sers des merges quand j'ai effectivement besoin d'intégrer le travail de ma branche vers sa parente, donc quand j'ai besoin de "livrer" le travail effectué sur ma branche. C'est une affaire de sens (direction) en fait…

Par contre, c'est vrai que quand je suis en local (ou sur une branche "à moi", qui n'est pas destinée - ou ne l'est pas encore - à être utilisée comme base pour quelqu'un d'autre, sinon ça devient vite un enfer…), mais pas à distance du coup. Sauf cas exceptionnels.

J'ai assez étalé mon avis sur les différents topics de branche pour le dev de zds :D

+0 -0

Le gros intéret des outils de versioning est de pouvoir revenir à n'importe quel version du code. En faisant un rebase tu perds ça et tu va avoir des commits intermédiaires qui ne correspondent pas aux vrais versions que tu as codé.

C'est exactement pour cette raison que le rebase est utile : comme l'a dit Höd, revenir à la version avant l'implémentation de telle fonctionnalité, c'est utile. Revenir à la version entre la correction d'une typo et le renommage d'une variable qui corrigent le même bug, ça n'a aucun intérêt.

Comme je l'ai dis, je n'ai rien contre le rebase d'une branche sur elle même, typiquement quand c'est pour regrouper des commits. Ce que je trouve inutile et contre productif c'est quand c'est un rebase d'une branche sur une autre. Typiquement ce que décrit Talus. Même pour un fix. Je ne vois pas le problème avec un merge en cours de route. Si on doit récupérer de nouveaux commits il devrait y avoir un merge. Car ça va déplacer les commits par dessus cette correction et on est pas surs que le code ainsi rebasé, dans les commits intermédiaire, est correct et ne représente en réalité jamais un vrai état du dev.

Donc oui pour moi un rebase pour réaranger son historique de branche je ne vois pas de soucis. Ce qui me gène ce sont les rebases quand on veut réunir deux branches. Là on devrait faire un merge.

Bof, on peut aussi avoir envie de réarranger un historique entre deux branches pour la même raison. Par exemple, pour éviter dans une pull request (depuis une branche sur laquelle on est seul à travailler, donc) d'avoir plusieurs commits "merge truc" qui en fait ne correspondent pas à une fusion, mais précisément à une réadaptation de sa branche sur celle vers laquelle on veut merger.

Quand tu bosse sur un gros projet, le mainteneur en a rien a foutre que tu a commencé a bossé sur ta feature y'a deux mois et d'avoir des diff par rapport a une vieille version. Tu rebase ton code avant de lui donner, pour qu'il puisse voir les diff par rapport à la version à jour.

Connectez-vous pour pouvoir poster un message.
Connexion

Pas encore membre ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte