Skip to content

Instantly share code, notes, and snippets.

@Cerdic
Created February 19, 2011 14:03
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Cerdic/835073 to your computer and use it in GitHub Desktop.
Save Cerdic/835073 to your computer and use it in GitHub Desktop.
suite
##Je me suis trompé
git commit --amend
permet de reprendre le dernier commit
en fait c'est equivalent a :
git reset HEAD^
qui revient a l'avant dernier commit et renvoie le diff dans le working tree
puis
git commit
git commit --amend -C HEAD
reprend le message de commit du head tel quel
git commit --amend -c HEAD
reprend le message de commit du head et permet moi de l'editer
git commit -a --amend -C HEAD
-a : ajoute les modifs unstaged
--amend : corrige le dernier commit
-C HEAD : reprend le message du dernier commit
pourrait etre dans une macro
git oops
git commit -a --amend -C HEAD --reset-author
permet de reprendre les droits d'auteur, bien utile quand on a commit
depuis un serveur de prod
##Quand on a deja pushe un commit ...
git revert
permet de creer un commit inverse d'un commit existant dans l'historique
permet de revenir dans l'etat ou on serait si ce commit n'avait pas eu lieu
## git reset
permet de modifier l'index des modifs staged
##j'ai stagé un fichier en trop
git reset -- fichier
git reset HEAD fichier
enleve de l'index la modif
Quand on est a l'initial import, il n'y a pas de HEAD :
git rm --cached fichier
enleve de l'index le fichier
## on annule tout
git reset --hard
annule toutes les modifs par rapport au HEAD. modifie l'index et le working tree, comme si ça n'avait jamais été fait. Supprime aussi les modifs untracked. On revient vraiment dans l'etat d'un git clone
git reset --merge
git pull
Auto-merging
...
git reset --merge ORIG_HEAD
permet d'annuler un merge qui a bien marché mais dont on ne veut finalement pas
git reset --keep
le merge part en vrille, on veut revenir dans l'etat de son working tree avant le merge
git reflog
affiche l'historique de position du HEAD, ce qui permet de retrouver n'importe quel commit, y compris si plus rien ne point dessus
git reflog
32ccd84 HEAD@{0}: revert: Revert "avec dependances"
cfab469 HEAD@{1}: commit (amend): avec dependances
fd0dd8c HEAD@{2}: commit: avec dependances
a0bdf47 HEAD@{3}: rebase -i (reword): rien a voir
50756b6 HEAD@{4}: rebase -i (pick): mon truc qui attendait
93a5468 HEAD@{5}: checkout: moving from master to 93a5468307459b44a842a3e65ccfa4c43bc20d89
b4020ee HEAD@{6}: checkout: moving from master to b4020ee
b4020ee HEAD@{7}: checkout: moving from master to b4020ee
b4020ee HEAD@{8}: commit: mon truc qui attendait
gitsession (master)$ git reset --hard cfab469
HEAD is now at cfab469 avec dependances
gitsession (master)$ git reflog
cfab469 HEAD@{0}: cfab469: updating HEAD
32ccd84 HEAD@{1}: revert: Revert "avec dependances"
cfab469 HEAD@{2}: commit (amend): avec dependances
fd0dd8c HEAD@{3}: commit: avec dependances
a0bdf47 HEAD@{4}: rebase -i (reword): rien a voir
50756b6 HEAD@{5}: rebase -i (pick): mon truc qui attendait
93a5468 HEAD@{6}: checkout: moving from master to 93a5468307459b44a842a3e65ccfa4c43bc20d89
b4020ee HEAD@{7}: checkout: moving from master to b4020ee
b4020ee HEAD@{8}: checkout: moving from master to b4020ee
b4020ee HEAD@{9}: commit: mon truc qui attendait
## git filter-branche
## la bombe nucléaire
Supprimer de l'index dans les commits un fichier envoye par erreur
git filter-branch --index-filter "git rm --cached fichierasupprimer" a0bdf47..
git prend chaque commit depuis a0bdf47 (non compris), et le modifie avec la commande passee
il réécrit le commit, le sha
tout l'arbre est modifié, et obigera tous ceux qui ont pull a re-checkout pour revenir sur le nouvel arbre
comme on utilise --index-filter git manipule directement l'index sans devoir checkout chaque commit
cf les autres options
cette commande n'est a utiliser qu'en cas de force majeure (suppression de l'arbre d'un fichier confidentiel)
## J'aurais du faire une branche
git branch nouvelle_fonction
git reset --hard HEAD~3
gitsession (fianet)$ git lg --all
* 471d3d7 - (HEAD, fianet) FIA.net (Cedric 2 minutes ago)
* cfab469 - (autreversion) avec dependances (Cedric 66 minutes ago)
* a0bdf47 - rien a voir (Cedric 3 hours ago)
* 50756b6 - mon truc qui attendait (Cedric 3 hours ago)
| * 010d9da - (master) on continue (Cedric 5 minutes ago)
|/
* 93a5468 - (origin/master) commit urgent (Cedric 4 hours ago)
* dc86655 - hop la suite (Cedric 5 hours ago)
* cdf5c84 - un commit partiel (Cedric 5 hours ago)
* c610f79 - hop (Cedric 5 hours ago)
* 9a0d271 - hop (Cerdic 5 hours ago)
* 47cbb70 - first commit (Cerdic 5 hours ago)
gitsession (fianet)$ git rebase --onto master autreversion
on rebase sur master, a partir de autreversion (jusqu'a l'etat courant)
ici on a des noms de branche qui permettent de nommer, mais on aurait pu utiliser les hash de la meme façon
First, rewinding head to replay your work on top of it...
Applying: FIA.net
on voit le résultat :
cedric@iMac-de-Cedric-2:gitsession (fianet)$ git lg --all
* f9ed2f8 - (HEAD, fianet) FIA.net (Cedric 4 seconds ago)
* 010d9da - (master) on continue (Cedric 7 minutes ago)
| * cfab469 - (autreversion) avec dependances (Cedric 68 minutes ago)
| * a0bdf47 - rien a voir (Cedric 3 hours ago)
| * 50756b6 - mon truc qui attendait (Cedric 3 hours ago)
|/
* 93a5468 - (origin/master) commit urgent (Cedric 4 hours ago)
* dc86655 - hop la suite (Cedric 5 hours ago)
* cdf5c84 - un commit partiel (Cedric 5 hours ago)
* c610f79 - hop (Cedric 5 hours ago)
* 9a0d271 - hop (Cerdic 5 hours ago)
* 47cbb70 - first commit (Cerdic 5 hours ago)
## Les submodules
submodules reference un sha précis, donc aucun auto-tracking
definit dans un .gitmodules a la racine du depot (a cote de .git)
installer un module :
git submodule add /Users/cedric/Sites/hbg/mymodule.git vendor/mymodule
le dossier mymodule pointe sur le repo distant et est géré indépendamment.
quand on clone un depot avec des modules
il faut commencer par
git submodule init
puis
git submodule update
mais le submodule chechout le commit reference dans le depot parent, en mode "detached head" : il faut se replacer sur la branche ou le tag manuellement si jamais on veut travailler dessus
les submodules sont toujours en detached head et sont un peu lourd à manier au quotidien
## Les subtrees
un seul depot avec des subtrees connectes sur un remote separe
git remote add plugin1 git://.....xxx.git
git fetch plugin1
mkdir -p vendor/cool
git checkout -b plugin1 plugin1/master
pour caler une brance locale dediee sur le repo partagé
git read-tree -prefix=vendor/cool/ -u plugin1
pour incorporer ça dans un sous repertoire du depot
git merge --squash -s subtree -no-commit
pour choper les modifs upstream
git diff-tree -p plugin1
pour voir les différences up-stream entre vendor/cool et la branche plugin1
git merge -s subtree --squash --no-commit plugin1
------
## Quels commits j'ai, deja ?
git branch --contains 010d9da
Quelle branche contient le commit 010d9da ?
git branch --merged
quelles branches ont ete fusionnées ?
git branch --no-merged
quelles branches trainent sans avoir été mergées ?
git cherry
trouver les commits qui n'ont pas été mergés
gitsession (fianet)$ git cherry -v HEAD autreversion
quels sont les commits qui ne sont pas dans HEAD mais qui sont dans autreversion
git cherry-pick
gitsession (fianet)$ git cherry-pick 50756b6
recupere le commit 50756b6 pour la branche actuelle
une alternative quand on est trans depot :
git show + git apply
## mais d'ou vient ce bug ?
on utilise git bisect pour faire une recherche dichotomique
on demarre la bisection en declarant que l'actuelle est mauvaise :
git-avance-support (master)$ git bisect start
cedric@iMac-de-Cedric-2:git-avance-support (master|BISECTING)$ git bisect bad
on passe ensuite sur la dernière revision bonne connue
cedric@iMac-de-Cedric-2:git-avance-support (master|BISECTING)$ git checkout dfb0e23
Note: checking out 'dfb0e23'.
You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by performing another checkout.
If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -b with the checkout command again. Example:
git checkout -b new_branch_name
HEAD is now at dfb0e23... Initial import
et on la declare bonne :
cedric@iMac-de-Cedric-2:git-avance-support ((dfb0e23...)|BISECTING)$ git bisect good
Ensuite git bisect procede a la dichotomie en proposant un commit a tester, un par un :
Bisecting: 4 revisions left to test after this (roughly 2 steps)
[9e9e1337873318260b6d22467a2a68aa63c741dd] Nouvelle fonction
cedric@iMac-de-Cedric-2:git-avance-support ((9e9e133...)|BISECTING)$ git bisect bad
Bisecting: 1 revision left to test after this (roughly 1 step)
[3fa6c45f447933ca092e5ce32fb13ed8ad699bd0] Alors là on va dire que j'ai pas vu que je collais un bug
cedric@iMac-de-Cedric-2:git-avance-support ((3fa6c45...)|BISECTING)$ git bisect bad
Bisecting: 0 revisions left to test after this (roughly 0 steps)
[9c632e158d03616448695e7b39ceff75a67da26b] Ah ben oui mais si je fais rien…
cedric@iMac-de-Cedric-2:git-avance-support ((9c632e1...)|BISECTING)$ git bisect good
3fa6c45f447933ca092e5ce32fb13ed8ad699bd0 is the first bad commit
commit 3fa6c45f447933ca092e5ce32fb13ed8ad699bd0
Author: Christophe Porteneuve <tdd@tddsworld.com>
Date: Sat Feb 19 09:34:07 2011 +0100
Alors là on va dire que j'ai pas vu que je collais un bug
:100644 100644 4babc8f311fb3b67a7f32fbeae0ee72728807db8 addc7a4f6e49560af07b853cff5bf37eead63209 M demo.rb
Jusqu'à ce que le premier commit bugué soit connu.
git-avance-support ((9c632e1...)|BISECTING)$ git bisect reset
Previous HEAD position was 9c632e1... Ah ben oui mais si je fais rien…
Switched to branch 'master'
et on finit la recherche dichotomique
si on sait automatiser le test en ligne de commande, on peut faire la recherche du bug de façon automatique
git bisect start HEAD dfb0e23
git bisect run montest.sh
-------------
## git rerere
REcord REuse REsolution
permet de faire un merge entre 2 branches et de le sauvegarder sans le commit
ainsi deux branches peuvent vivre leur vie en parallèles en s'assurant régulièrement que le merge final se passera sans soucis, sans pour autant commit le merge, sauf à la fin.
Git reutilisera alors les resolutions intermédiaires enregistrées.
De plus, ces résolutions sont mémorisées dans le dépôt et peuvent donc être utilisées également par les copains.
On commence par activer de façon permanente la mémorisation des résolutions car par défaut git ne conserve que dans un délai défini.
git config --global rerere.enabled 1
git-avance-support (other-way)$ git merge master
Auto-merging demo.rb
CONFLICT (content): Merge conflict in demo.rb
Recorded preimage for 'demo.rb'
Automatic merge failed; fix conflicts and then commit the result.
cedric@iMac-de-Cedric-2:git-avance-support (other-way *+|MERGING)$ git st
# On branch other-way
# Unmerged paths:
# (use "git add/rm <file>..." as appropriate to mark resolution)
#
# both modified: demo.rb
#
On resoud le conflit :
cedric@iMac-de-Cedric-2:git-avance-support (other-way *+|MERGING)$ nano demo.rb
cedric@iMac-de-Cedric-2:git-avance-support (other-way *+|MERGING)$ git st
# On branch other-way
# Unmerged paths:
# (use "git add/rm <file>..." as appropriate to mark resolution)
#
# both modified: demo.rb
#
no changes added to commit (use "git add" and/or "git commit -a")
cedric@iMac-de-Cedric-2:git-avance-support (other-way *+|MERGING)$ git add demo.rb
git-avance-support (other-way|MERGING)$ git commit -m"resolution"
Recorded resolution for 'demo.rb'.
[other-way 4b3bfea] resolution
Puis on peut revenir dans l'etat precedent :
git-avance-support (other-way)$ git reset HEAD^
ou si on ne veut pas garder les modifs dans le working directory :
git-avance-support (other-way)$ git reset --hard HEAD^
Dans tous les cas la resolution est memorisée et sera utilisée plus tard quand on remergera
Quand ulterieurement on remerge :
git-avance-support (other-way)$ git merge master
Auto-merging demo.rb
CONFLICT (content): Merge conflict in demo.rb
Resolved 'demo.rb' using previous resolution.
Automatic merge failed; fix conflicts and then commit the result.
cedric@iMac-de-Cedric-2:git-avance-support (other-way *+|MERGING)$ git diff
diff --cc demo.rb
index 06bb686,c5b894a..0000000
--- a/demo.rb
+++ b/demo.rb
Meme si git a bien utilise la resolution memorisée, il indique que tout n'etait pas trivial et s'abstient de generer le commit automatiquement.
git rerere status
git rerere diff
permettent d'en savoir plus, dans le contexte de rerere sur le merge en cours
### Workflows
1 remote vs plusieurs remote
L'utilisation de plusieurs remote forkés se justifie surtout sur les projets ouverts massivement contribués.
Sinon un seul remote est la plupart du temps suffisant et plus simple à gérer, à partir du moment ou un peu de coordination est maintentue. Cela d'autant plus que chacun a en puissance sur sa machine un repo forké qu'il peut utiliser pour toute sorte d'experimentaiton.
### Branches
http://nvie.com/posts/a-successful-git-branching-model/
Une branche develop qui sert au quotidien pour le dev du projet
Des features/topic branches dédiées à une fonctionnalité, qui sont régulièrement mergées dans la branche develop
Une release branch est créée quand on passe en phase de debug, avec backport des bugfix sur developp
Quand la release est jugée stable, on tag sur master la release
Quand un bug grave est détecté sur une stable, on branche sur hotfix pour corriger (on ne travaille jamais sur master). Quand le correctif est OK, on tag une mineure sur master, et on renvoi le fix sur develop
###
Ressource de référence ProGit qui est gratuit en ligne (mais en anglais)
http://progit.org/book/
qui existe aussi en version papier
Outil GUI pour Mac :
http://www.git-tower.com/
mais payant
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment