J'utilise Git depuis quelques mois sur un projet avec un autre développeur. J'ai plusieurs années d'expérience avec SVN , donc je suppose que j'apporte beaucoup de bagages à la relation.
J'ai entendu dire que Git est excellent pour les branchements et les fusions, et jusqu'à présent, je ne le vois pas. Bien sûr, la ramification est très simple, mais quand j'essaye de fusionner, tout va tout au diable. Maintenant, je suis habitué à cela de SVN, mais il me semble que je viens d'échanger un système de version sous-pair pour un autre.
Mon partenaire me dit que mes problèmes proviennent de mon désir de fusionner bon gré mal gré et que je devrais utiliser rebase au lieu de fusionner dans de nombreuses situations. Par exemple, voici le workflow qu'il a défini:
clone the remote repository
git checkout -b my_new_feature
..work and commit some stuff
git rebase master
..work and commit some stuff
git rebase master
..finish the feature
git checkout master
git merge my_new_feature
Essentiellement, créez une branche de fonction, TOUJOURS rebaser du maître à la branche et fusionner de la branche au maître. Il est important de noter que la succursale reste toujours locale.
Voici le workflow avec lequel j'ai commencé
clone remote repository
create my_new_feature branch on remote repository
git checkout -b --track my_new_feature origin/my_new_feature
..work, commit, push to origin/my_new_feature
git merge master (to get some changes that my partner added)
..work, commit, push to origin/my_new_feature
git merge master
..finish my_new_feature, push to origin/my_new_feature
git checkout master
git merge my_new_feature
delete remote branch
delete local branch
Il y a deux différences essentielles (je pense): j'utilise toujours la fusion au lieu du rebasage, et je pousse ma branche de fonctionnalité (et ma branche de fonctionnalité se valide) vers le référentiel distant.
Mon raisonnement pour la branche distante est que je veux que mon travail soit sauvegardé pendant que je travaille. Notre référentiel est automatiquement sauvegardé et peut être restauré en cas de problème. Mon ordinateur portable n'est pas, ou pas aussi complètement. Par conséquent, je déteste avoir du code sur mon ordinateur portable qui ne se reflète pas ailleurs.
Mon raisonnement pour la fusion au lieu de rebaser est que la fusion semble être standard et rebaser semble être une fonctionnalité avancée. Mon instinct est que ce que j'essaie de faire n'est pas une configuration avancée, donc le rebase ne devrait pas être nécessaire. J'ai même parcouru le nouveau livre de programmation pragmatique sur Git, et ils couvrent largement la fusion et mentionnent à peine le rebase.
Quoi qu'il en soit, je suivais mon flux de travail sur une branche récente, et quand j'ai essayé de le fusionner à nouveau en master, tout est allé en enfer. Il y a eu des tonnes de conflits avec des choses qui n'auraient pas dû avoir d'importance. Les conflits n'avaient tout simplement aucun sens pour moi. Il m'a fallu une journée pour tout régler, et a finalement abouti à une poussée forcée vers le maître distant, car mon maître local a résolu tous les conflits, mais le distant n'était toujours pas satisfait.
Quel est le flux de travail "correct" pour quelque chose comme ça? Git est censé rendre les branchements et les fusions super faciles, et je ne le vois tout simplement pas.
Mise à jour 2011-04-15
Cela semble être une question très populaire, alors j'ai pensé que je mettrais à jour mes deux années d'expérience depuis ma première demande.
Il s'avère que le flux de travail d'origine est correct, au moins dans notre cas. En d'autres termes, c'est ce que nous faisons et cela fonctionne:
clone the remote repository
git checkout -b my_new_feature
..work and commit some stuff
git rebase master
..work and commit some stuff
git rebase master
..finish the feature, commit
git rebase master
git checkout master
git merge my_new_feature
En fait, notre flux de travail est un peu différent, car nous avons tendance à faire des fusions de squash au lieu de fusions brutes. ( Remarque: cela est controversé, voir ci-dessous. ) Cela nous permet de transformer l'ensemble de notre branche de fonctionnalités en un seul commit sur master. Ensuite, nous supprimons notre branche de fonctionnalités. Cela nous permet de structurer logiquement nos commits sur master, même s'ils sont un peu désordonnés sur nos branches. Voici donc ce que nous faisons:
clone the remote repository
git checkout -b my_new_feature
..work and commit some stuff
git rebase master
..work and commit some stuff
git rebase master
..finish the feature, commit
git rebase master
git checkout master
git merge --squash my_new_feature
git commit -m "added my_new_feature"
git branch -D my_new_feature
Controverse de fusion de squash - Comme plusieurs commentateurs l'ont souligné, la fusion de squash va jeter tout l'historique de votre branche de fonctionnalités. Comme son nom l'indique, il écrase tous les commits en un seul. Pour les petites fonctionnalités, cela a du sens car il les condense vers le bas dans un seul paquet. Pour les fonctionnalités plus importantes, ce n'est probablement pas une bonne idée, surtout si vos commits individuels sont déjà atomiques. Cela se résume vraiment à la préférence personnelle.
Github et Bitbucket (autres?) Demandes Pull - Au cas où vous vous demandez comment la fusion / rebase est liée aux demandes Pull, je vous recommande de suivre toutes les étapes ci-dessus jusqu'à ce que vous soyez prêt à fusionner à nouveau vers le maître. Au lieu de fusionner manuellement avec git, vous acceptez simplement le PR. Notez que cela ne fera pas de fusion de squash (du moins pas par défaut), mais que le non-squash, l'avance rapide n'est pas la convention de fusion acceptée dans la communauté Pull Request (pour autant que je sache). Plus précisément, cela fonctionne comme ceci:
clone the remote repository
git checkout -b my_new_feature
..work and commit some stuff
git rebase master
..work and commit some stuff
git rebase master
..finish the feature, commit
git rebase master
git push # May need to force push
...submit PR, wait for a review, make any changes requested for the PR
git rebase master
git push # Will probably need to force push (-f), due to previous rebases from master
...accept the PR, most likely also deleting the feature branch in the process
git checkout master
git branch -d my_new_feature
git remote prune origin
J'ai appris à aimer Git et je ne veux plus jamais revenir à SVN. Si vous avez du mal, restez avec et finalement vous verrez la lumière au bout du tunnel.
rebase
comprendre