-1
votes

Est-il préférable d'utiliser git pull --rebase que git pull --ff-only

Dans notre équipe, nous voulons maintenir une histoire git linéaire.

Nous avons exécuté ces commandes:

l'utilisateur met à jour certains fichiers

git pull --rebase
<fixup any issues>
git add .
git rebase --continue

Mais on voit souvent:

mkdir gitserver
mkdir gitclient1
mkdir gitcleint2

# server side
cd gitserver
git init --bare diverge.git

#client 1
cd gitclient1
git clone ../gitserver/diverge.git
cd diverge
<create index.html file with a few lines of text, save.>
git add .
git commit -m "first commit by user 1"
git push

#client 2
cd gitclient2
git clone ../gitserver/diverge.git
cd diverge
add a new line to index.html
git add .
git commit -m "changed line made by user 2"
git push

# back to client 1
$ git pull --ff-only
remote: Counting objects: 3, done.
remote: Compressing objects: 100% (2/2), done.
remote: Total 3 (delta 1), reused 0 (delta 0)
Unpacking objects: 100% (3/3), done.
From D:/projects/git/git_diverge_test/gitclient1/../gitserver/diverge
   7208075..ce21832  master     -> origin/master
fatal: Not possible to fast-forward, aborting.

Je me demande si les commandes git que j'utilise pourraient être améliorées? Par exemple, en utilisant git pull --rebase au lieu de git pull --ff-only?

Étapes à suivre pour reproduire.

créer 3 répertoires:

fatal: Not possible to fast-forward, aborting.

Pourquoi est-ce que je reçois le message fatal?

Git n'aurait-il pas dû être capable d'extraire le commit par-dessus le commit existant?

Et si je lance gitk --all, je vois que master est sur une autre 'branche' de l'arborescence de remote / origin / master.

Une approche qui fonctionne dans une certaine mesure consiste à utiliser:

git add .
git commit
git pull --ff-only

Est-ce que git pull --rebase est en quelque sorte plus dangereux?

git

9 commentaires

Quel est le problème avec une traction régulière?


@evolutionxbox Je pense que l'idée est de maintenir un historique git linéaire, c'est-à-dire pas de branches fusionnées. Je pense que git pull s'il échoue pourrait provoquer une histoire non linéaire. Bien que je puisse me tromper là-bas.


Pourquoi une histoire linéaire est-elle souhaitée? (curieux) --- Aussi, quel est le problème à propos de l'utilisation de --rebase ? Comment penser que cela pourrait être plus dangereux?


@evolutionxbox Je ne connais pas la raison de la décision.


Qu'obtenez-vous si vous exécutez git branch -vv partir du client 1 et du client 2?


@prosoitos user1: $ git branch -vv -> * master 3e32b6a [origin / master] une 3e nouvelle ligne ajoutée par l'utilisateur 1


@prosoitos user2: $ git branch -vv -> * master fff89e8 [origin / master: ahead 1, behind 1] une 3ème nouvelle ligne ajoutée par l'utilisateur


J'ai essayé tes pas pour reproduire. Ils ne se reproduisent pas. Vous devez avoir commis quelque chose d'autre dans client1 après le clonage de client2, et obligé client1 à avoir un nouveau commit à l'extrémité de la branche. C'est ce qui cause l'erreur non transférable.


Oui. Et vous pouvez le voir dans la sortie de git branch : ahead 1 est ce à quoi vous vous attendez, mais behind 1 vous indique clairement que vous avez créé des branches divergentes.


3 Réponses :


2
votes

Réponse courte: utilisez git pull --rebase

Tout d'abord, votre exemple ne fonctionne pas, le client 1 aurait besoin de valider autre chose avant le pull --ff-only , mais supposons que nous l'avons fait.

Pourquoi git pull --ff-only échoue?

Cette commande demande à git de fetch le dernier état de la télécommande et d'avancer rapidement la branche si possible. Donc, si nous avons des changements différents sur la branche distante et locale, cela s'arrêtera, car c'est ce que nous lui avons dit de faire avec --ff-only

Que fera git pull --rebase ?

Il fetch également, mais après cela, il fera un git rebase origin/master . Witch prendra tous les commits sur le maître qui ne sont pas déjà sur la télécommande et les rebasera à la fin de l'origine / du maître. Bien sûr, vous devrez peut-être résoudre les conflits de fusion qui surviennent. Le seul danger que je vois est que vous devriez tester ce qui se passe si vous avez des commits de fusion dans votre branche, mais puisque vous voulez un historique linéaire, cela ne devrait pas être un problème pour vous.


0 commentaires

2
votes

Flux de travail à avance rapide uniquement

Le flux de travail que vous présentez ne doit autoriser que les tirages d'avance rapide. Cependant, pour que cela fonctionne, vous avez besoin d'une coordination parfaite entre les membres de l'équipe travaillant sur différents clients et vous ne pouvez travailler que sur un client à la fois .

Par exemple, alors que quelqu'un travaille sur le client 1, les gens ne peuvent pas créer de commits sur le client 2 et vice versa. Si les commits sont créés simultanément sur les deux clients, vous vous retrouverez avec des historiques divergents qui devront être fusionnés avec un commit ou rebasés: une fusion rapide ne sera pas possible.

Ce n'est pas vraiment pratique (comme l'expérience vous l'a appris: le message d'erreur que vous obtenez et les sorties de git branch -vv et gitk --all vous montrent tous que vous vous êtes retrouvé avec des histoires divergentes sur les 2 clients sans le vouloir et sans vous en rendre compte il). Il s'agit également d'un flux de travail non efficace car tous les clients sauf un doivent être en attente à tout moment. Un bon flux de travail de contrôle de version devrait permettre à différentes personnes de travailler simultanément, puis d'intégrer leur travail dans le projet.

Rebase

Dès que différentes personnes ont créé des commits simultanément sur différents clients, vous avez besoin de commits de fusion ou de rebases. Les validations de fusion créent des historiques non linéaires, donc si vous voulez un historique linéaire, vous devez rebaser.

Cela peut en effet être fait avec git pull --rebase .

Le rebasage est une réécriture de l'histoire et il est dangereux de le faire sur des commits qui ont déjà été poussés vers une télécommande, mais c'est sûr de le faire sur des commits non publiés.

Lorsque vous exécutez git pull --rebase , la branche actuelle est rebasée au-dessus de la branche amont fraîchement récupérée. Donc, c'est l'histoire de votre succursale locale qui est réécrite, pas celle de l'amont. Ainsi, tant que votre équipe n'utilise qu'une seule télécommande pour synchroniser le travail, vous pouvez fusionner les modifications de cette télécommande dans la vôtre avec git pull --rebase sans risquer de créer des problèmes pour les autres.

Réécrire l'historique sur un flux de travail non linéaire

Une autre alternative serait de fusionner avec git pull --ff qui fera des fusions d'avance rapide lorsque cela est possible, mais créera des commits de fusion lorsque ce n'est pas possible, puis réécrira l'historique du projet de temps en temps pour le rendre linéaire. Ces réécritures de l'histoire pourraient être coordonnées au niveau de l'équipe, bloquant toute activité du projet lorsqu'elles surviennent, pour éviter tout problème.

Une façon de le faire serait d'utiliser git reset comme cela est présenté dans la section Squashing près du bas de cette section du Pro Git Book.

Cependant, un inconvénient de cette méthode est que vous perdrez les petites étapes introduites par chaque commit. C'est aussi une approche beaucoup plus tortueuse et cela peut être dangereux si quelqu'un ne respecte pas le gel de l'activité lors de la réécriture de l'histoire (sans oublier que de tels gels ne sont pas efficaces).

Conclusion

En conclusion, utiliser git pull --rebase est probablement la meilleure solution ici.

Remarque

Vous pouvez définir ceci comme comportement par défaut pour git pull avec:

git config --global pull.rebase true

(Supprimez --global si vous ne le souhaitez que pour un projet).


0 commentaires

2
votes

Pour placer votre travail local au-dessus de la branche distante: utilisez git pull --rebase .

S'il s'agit du flux de travail prévu pour toute votre équipe: que tout le monde soit défini

git fetch                # will update all remote branches
git fetch origin branch  # if you want to update one single branch from the remote

et git pull se traduira maintenant par git pull --rebase .


L'utilisation prévue de git pull --ff-only est:

  • lorsque vous n'avez pas de travail local en plus de la branche actuelle,
  • et vous souhaitez mettre à jour cette branche vers son homologue distant,
  • et assurez-vous de ne pas créer accidentellement un commit de fusion.

Si vous avez le travail local sur le dessus de la branche, git pull --ff-only ne fera jamais l' action:

  1. soit votre version de la télécommande est déjà à jour (donc aucune mise à jour n'est nécessaire),
  2. ou quelqu'un d'autre l'a modifié, et l'intégration de ces mises à jour ne sera jamais une fusion rapide (donc la mise à jour sera annulée).

Si vous souhaitez importer la branche distante pour vérifier si elle a été mise à jour: utilisez git fetch

git config pull.rebase true

Après avoir exécuté git fetch , vous pouvez comparer votre branche et origin/branch (utilisez un visualiseur git, ou git log --graph --oneline HEAD origin/branch ), vous pouvez rebaser votre travail au-dessus de l' origin/branch (en exécutant: git rebase origin/branch ), etc ...


0 commentaires