mirroir readonly du Gitit wiki.evolix.org (attention, ne rien commiter/merger sur ce dépôt) https://wiki.evolix.org
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

HowtoGit.md 25 KiB

2 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
2 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
1 year ago
3 years ago
2 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
2 years ago
2 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
2 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
2 years ago
2 years ago
2 years ago
2 years ago
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030
  1. ---
  2. categories: git
  3. title: Howto Git
  4. ...
  5. * Documentation: <https://git-scm.com/doc>
  6. * À lire : <https://progit.org/>
  7. * À voir : <https://youtu.be/4XpnKHJAok8>
  8. [Git](https://git-scm.com/) est un logiciel de gestion de code source, créé en 2005 par Linus Torvalds.
  9. ## Installation
  10. ~~~
  11. # apt install git gitg
  12. ~~~
  13. Configuration minimale via `~/.gitconfig` :
  14. ~~~
  15. [user]
  16. name = John Doe
  17. email = jdoe+git@example.com
  18. [pull]
  19. rebase = true
  20. [push]
  21. default = simple
  22. [core]
  23. editor = vim
  24. ~~~
  25. ## Commandes de base
  26. ### Utilisation et pages de manuel
  27. Les commandes Git s'utilisent sous la forme `git <commande> [options]`
  28. Pour chaque commande, une page de manuel *git-<commande>* est disponible. Par exemple pour `git add` faire `man git-add`.
  29. ### Créer un dépôt
  30. ~~~
  31. $ mkdir foo
  32. $ cd foo
  33. $ git init
  34. ~~~
  35. >> Note : dans le cas où on crée un dépôt en mode « serveur », on utilisera l'argument `--bare`.
  36. ### Cloner un dépôt
  37. Plusieurs méthodes d'accès pour récupérer un dépôt : ssh://, http(s)://, git://, file:// etc.
  38. ~~~
  39. $ git clone ssh://git.example.com/path/projet.git
  40. $ git clone https://git.example.com/path/projet
  41. $ git clone git://git.example.com/path/projet.git
  42. $ git clone file:///path/projet
  43. ~~~
  44. ### Travailler sur un dépôt local
  45. Ajouter un nouveau fichier :
  46. ~~~
  47. $ touch main.c
  48. $ git add main.c
  49. $ git commit -v
  50. ~~~
  51. Modification d'un fichier existant :
  52. ~~~
  53. $ vi main.c
  54. $ git add main.c
  55. $ git commit -v
  56. ~~~
  57. *Note* : si l'on souhaite faire un commit de l'ensemble des fichiers modifiés (et suivis) par git, on peut utiliser la commande `git
  58. commit -a` sans avoir à utiliser `git add`. Néanmoins c'est une habitude à éviter car on risque d'inclure dans le commit des modifications non souhaitées.
  59. Supprimer un fichier du dépôt (et non en local) :
  60. ~~~
  61. $ git rm --cached fichier
  62. ~~~
  63. Voir l'état du dépôt local (fichiers non commités, etc.) :
  64. ~~~
  65. $ git status
  66. $ git status -s -b
  67. ~~~
  68. Voir les derniers commits du dépôt local :
  69. ~~~
  70. $ git log
  71. ~~~
  72. ### pull/push avec un dépôt distant
  73. Si l'on a cloné un dépôt existant, un lien est automatiquement créé entre le dépôt local créé et le dépôt distant (référencé comme *origin*).
  74. Pour récupérer en local les derniers changements du dépôt distant :
  75. ~~~
  76. $ git pull --rebase origin
  77. ~~~
  78. *Note* : l'option `--rebase` est désormais le défaut mais par pédagogie on conseille de la mettre explicitement.
  79. Pour envoyer ses modifications locales vers le dépôt référencé comme distant :
  80. ~~~
  81. $ git push origin
  82. ~~~
  83. ### Gestion des branches
  84. Par défaut, certains outils utilisent une branche nommée *master*.
  85. Cette branche existe donc souvent au sein d'un dépôt, mais il faut
  86. garder en tête que c'est une convention, rien n'oblige à en avoir une.
  87. Lister les branches existantes et connaître sa branche courante :
  88. ~~~
  89. $ git branch -a
  90. ~~~
  91. Passer d'une branche à une autre dans son dépôt local :
  92. ~~~
  93. $ git checkout myfeature
  94. $ git checkout master
  95. ~~~
  96. Créer une branche *myfeature* à partir de la branche *master* :
  97. ~~~
  98. $ git checkout master
  99. $ git branch myfeature master
  100. ~~~
  101. Renommer la branche courante :
  102. ~~~
  103. $ git branch -m <nouveau nom>
  104. ~~~
  105. Renommer une branche autre que la branche courante :
  106. ~~~
  107. $ git branch -m <ancien nom> <nouveau nom>
  108. ~~~
  109. Travailler sur la branche *myfeature* puis [merger](#git-merge) son travail dans la branche *master* :
  110. ~~~
  111. $ git checkout master
  112. $ git merge --no-ff myfeature
  113. ~~~
  114. Pousser une branche locale vers le dépôt référencé comme distant :
  115. ~~~
  116. $ git push origin myfeature
  117. ~~~
  118. Supprimer une branche locale et distante :
  119. ~~~
  120. $ git branch -d myfeature
  121. $ git push origin :myfeature
  122. ~~~
  123. Supprimer les branches locales qui ne sont pas présentes sur le dépôt distant :
  124. ~~~
  125. $ git fetch -p
  126. ~~~
  127. ## Commandes avancées
  128. ### Afficher l'historique
  129. Affichage de l'historique de différentes façons :
  130. ~~~
  131. $ git log
  132. $ git log -p
  133. $ git log --stat
  134. $ git log --summary
  135. $ git log --color
  136. $ git log --graph
  137. $ git log --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset'
  138. ~~~
  139. Afficher seulement les fichiers modifié :
  140. ~~~
  141. $ git log --name-only
  142. $ git show --name-only COMMIT
  143. ~~~
  144. On peut notamment combiner toutes ces options dans un alias à mettre dans `.gitconfig` :
  145. ~~~
  146. [alias]
  147. lg = log --color --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset'
  148. ~~~
  149. On peut aussi utiliser *whatchanged* qui va lister tout ce qui a changé :
  150. ~~~
  151. $ git whatchanged
  152. $ git whatchanged -p
  153. ~~~
  154. Voir l'avant-dernier commit :
  155. ~~~
  156. $ git show HEAD~1
  157. ~~~
  158. Voir le fichier *foo/bar* tel qu'il était dans l'avant-dernier commit :
  159. ~~~
  160. $ git show HEAD~1:foo/bar
  161. ~~~
  162. Pour voir ce qu'il s'est passé entre deux commits :
  163. ~~~
  164. $ git show HEAD~8..HEAD
  165. $ git show -p HEAD~8..HEAD
  166. ~~~
  167. On peut voir graphiquement l'historique avec différents outils, par exemple *gitg*, *gitk* ou *tig* :
  168. ~~~
  169. # apt install gitk gitg tig
  170. $ gitg
  171. $ gitk --all
  172. $ tig
  173. ~~~
  174. ### Modifier l'historique
  175. /!\\ Les modifications de l'historique ne doivent avoir lieu que si cela n'a pas été pushé vers un dépôt partagé !
  176. Modifier son dernier message de commit :
  177. ~~~
  178. $ git commit --amend
  179. ~~~
  180. Modifier son dernier commit :
  181. ~~~
  182. $ vi main.c
  183. $ git add main.c
  184. $ git commit --amend
  185. ~~~
  186. Modifier son avant-dernier commit :
  187. ~~~
  188. $ git rebase -i HEAD^^
  189. … remplacer « pick » par « edit » pour le commit à modifier
  190. $ vi main.c
  191. $ git add main.c
  192. $ git commit --amend
  193. $ git rebase --continue
  194. ~~~
  195. *Note* : On peut remonter au Nième commit en utilisant *HEAD~N*
  196. ### Picorer un commit d'une autre branche (cherry-pick)
  197. <https://git-scm.com/docs/git-cherry-pick>
  198. Récupérer un commit d'une autre branche dans master :
  199. ~~~
  200. $ git checkout master
  201. $ git cherry-pick <SHA1 du commit>
  202. ~~~
  203. Si tout se passe bien, il ne demandera rien de plus sauf s'il y a des conflits. Dans ce cas, il faut éditer les fichiers où la commande `git status` indique "modifié des deux côtés : conflit.txt".
  204. Après avoir effectué ces modifications, il faudra lancer la commande suivante pour confirmer l'action :
  205. ~~~
  206. $ git cherry-pick --continue
  207. ~~~
  208. Sinon pour tout annuler :
  209. ~~~
  210. $ git cherry-pick --abort
  211. ~~~
  212. ### gitignore
  213. <https://git-scm.com/docs/gitignore>
  214. Créer un fichier `.gitignore` à la racine pour ignorer certains fichiers/chemins :
  215. ~~~
  216. $ cat .gitignore
  217. test.php
  218. htdocs/foo/bar
  219. foo/bar*
  220. ~~~
  221. > **Note** : Le fichier `.gitignore` se commit dans le dépôt.
  222. > **Note** : Si on veut ignorer un fichier déjà commité, il faudra le supprimer de l'indexe avec `git rm --cached <file>`.
  223. On peut également avoir un fichier `~/.config/git/ignore` qui sera valable pour tous les dépôts Git.
  224. ### Ranger temporairement son travail (git stash)
  225. <https://git-scm.com/docs/git-stash>
  226. Cela permet d'avoir un buffer pour mettre « en pause » des modifications non commitées :
  227. ~~~
  228. …hack…hack…
  229. $ git stash save
  230. ~~~
  231. On peut lister ce buffer :
  232. ~~~
  233. $ git stash list
  234. stash@{0}: WIP on dev: fb1fa70… m
  235. stash@{1}: WIP on dev: fb1fa70… m
  236. ~~~
  237. Pour appliquer la dernière modification stockée :
  238. ~~~
  239. $ git stash pop
  240. ~~~
  241. Pour purger le buffer sans l'appliquer :
  242. ~~~
  243. $ git stash clear
  244. ~~~
  245. Pour voir une des modifications :
  246. ~~~
  247. $ git stash show -p stash@{0}
  248. ~~~
  249. Pour retrouver un stash pop grâce à gitk :
  250. ~~~
  251. gitk --all $( git fsck --no-reflog | awk '/dangling commit/ {print $3}' )
  252. ~~~
  253. ### git diff
  254. <https://git-scm.com/docs/git-diff>
  255. Voir les modifications locales non commitées et non indexés :
  256. ~~~
  257. $ git diff
  258. ~~~
  259. Voir les modifications locales *suivies* (ajoutées avec *git add*) :
  260. ~~~
  261. $ git diff --cached
  262. ~~~
  263. Voir les modifications entre deux commits, ou entre deux branches :
  264. ~~~
  265. $ git diff HEAD^ HEAD
  266. $ git diff HEAD~8 HEAD^^
  267. $ git diff myfeature master
  268. ~~~
  269. *Note* : si le 2ème commit est *HEAD* on peut ne pas le mentionner, `git diff HEAD^` montrera les modifications du dernier commit
  270. Voir les modifications entre deux commits, mais uniquement pour un fichier *foo* :
  271. ~~~
  272. $ git diff HEAD~8..HEAD^^ -- foo
  273. ~~~
  274. Avoir un diff inversé (pratique pour faire préparer un revert partiel par exemple) :
  275. ~~~
  276. $ git diff -R
  277. ~~~
  278. Avoir des stats entre 2 commits ou branches :
  279. ~~~
  280. $ git diff --stat HEAD~8 HEAD^^
  281. $ git diff --stat myfeature master
  282. ~~~
  283. Voir les modifications en mode "mots" plutôt qu'en mode "ligne" (très pratiques pour voir les changements au sein d'une ligne) :
  284. ~~~
  285. $ git diff --word-diff
  286. ~~~
  287. Voir les modifications depuis un certain temps sur un dépôt complet ou sur un fichier précis :
  288. ~~~
  289. $ git diff HEAD 'HEAD@{3 hours ago}'
  290. $ git diff HEAD 'HEAD@{3 weeks ago}' -- foo/bar.txt
  291. ~~~
  292. ### git pull/fetch
  293. <https://git-scm.com/docs/git-pull>
  294. `git pull` est une commande qui effectue un rapatriement des données (`git fetch`) puis l'intégration de ces données via `git rebase` (par défaut) ou `git merge`.
  295. <https://git-scm.com/docs/git-fetch>
  296. Dans certains cas il est pratique de faire un simple `git fetch`, notamment si l'on veut faire des manipulations complexes ou si l'on veut avoir toutes les données pour travailler hors ligne sans rien changer à l'état actuel de sa *working copy*.
  297. ### git push
  298. <https://git-scm.com/docs/git-push>
  299. Pousser toutes ses branches d'un coup (ce qui est déconseillé en général) :
  300. ~~~
  301. $ git push --all origin
  302. ~~~
  303. Si l'on a une branche locale nommée *foo* et que l'on veut la pousser dans la branche nommée *bar* du dépôt distant :
  304. ~~~
  305. $ git push origin foo:bar
  306. ~~~
  307. /!\\ Attention, il ne faut jamais modifier un historique qui a été pushé vers un dépôt partagé. Néanmoins dans certaines situations exceptionnelles (un mot de passe ou un email qui aurait été mis par erreur) on peut être amené à faire un `push --force` :
  308. ~~~
  309. $ git push -f origin
  310. ~~~
  311. Il faudra ensuite que chaque utilisateur du dépôt soit prévenu et accepte d'écraser leur dépôt local (en faisant ou vérifiant les modifications d'historiques) :
  312. ~~~
  313. $ git fetch
  314. $ git reset origin
  315. ~~~
  316. ### git checkout
  317. <https://git-scm.com/docs/git-checkout>
  318. Pour avoir le dépôt tel qu'il était à un commit :
  319. ~~~
  320. $ git checkout <SHA1 du commit>
  321. ~~~
  322. Ou, un fichier spécifique tel qu'il était à un commit :
  323. ~~~
  324. $ git checkout <SHA1 du commit> -- <fichier>
  325. ~~~
  326. On est alors dans l'état « HEAD détachée ». Pour revenir dans l'état précédent :
  327. ~~~
  328. $ git checkout -
  329. ~~~
  330. Pour se remettre sur la version courante :
  331. ~~~
  332. $ git checkout master
  333. ~~~
  334. Pour créer une branche et switcher directement dans cette nouvelle branche, on utilise l'option `-b` :
  335. ~~~
  336. $ git checkout -b myfeature
  337. ~~~
  338. Pour annuler toutes les modifications d'un fichier foo/ non indexé :
  339. ~~~
  340. $ git checkout foo/
  341. ~~~
  342. ### git branch
  343. <https://git-scm.com/docs/git-branch>
  344. Une branche est en fait la création une déviation, un commit qui a deux *enfants*.
  345. On peut ainsi créer une branche à partir de n'importe quel commit :
  346. ~~~
  347. $ git branch newbranch e150b8517a694a2d4816cff95ef612086d644f67
  348. ~~~
  349. Pour supprimer la branche *foo* sur un dépôt distant non cloné :
  350. ~~~
  351. $ git push ssh://git.example.com/projet.git :foo
  352. ~~~
  353. Pour récupérer une nouvelle branche depuis le dépôt référencé comme distant :
  354. ~~~
  355. $ git remote update
  356. ~~~
  357. ### git reset/clean
  358. <https://git-scm.com/docs/git-reset>
  359. <https://git-scm.com/docs/git-clean>
  360. /!\\ Certaines commandes peuvent provoquer une perte de données !
  361. Pour supprimer toutes les modifications non commitées et les fichiers/répertoires non indexés :
  362. ~~~
  363. $ git reset --hard
  364. $ git clean -f -d
  365. ~~~
  366. On peut aussi `git reset` sur des commits précédents (*HEAD^*,*HEAD~N*,*<SHA1 du commit>*).
  367. Ou même sur une branche distante comme *origin/master* par exemple (ce qui est pratique si l'historique de la branche distante a été modifié).
  368. Pour désindexer des modifications d'un fichier :
  369. ~~~
  370. $ git reset HEAD <fichier>
  371. ~~~
  372. ### git add
  373. <https://git-scm.com/docs/git-add>
  374. Pour ajouter tout un répertoire et son contenu :
  375. ~~~
  376. $ git add foo/
  377. ~~~
  378. Pour choisir ce que l'on veut ajouter pour le prochain commit :
  379. ~~~
  380. $ git add -p
  381. ~~~
  382. ### git merge
  383. <https://git-scm.com/docs/git-merge>
  384. Un merge consiste à créer un commit qui aura deux parents, et permet ainsi de fusionner deux branches existantes.
  385. Quand un merge est très simple, c’est-à-dire que cela rajoute simplement des commits sur une branche qui n'a pas bougé entre temps, on n'a pas besoin de créer un commit pour fusionner, on appelle cela un merge **fast-forward**. Cela se fait automatiquement avec la commande `git merge`. Notons que l'on peut vouloir tout de même avoir un commit pour marquer le coup et forcer un commit de merge avec l'option `git merge --no-ff`.
  386. Quand un merge n'est pas simple, Git peut adopter plusieurs stratégies (resolve, recursive, ours, theirs, patience, etc.). Il est probable que cela génère des conflits qui devront être résolus manuellement.
  387. ### git apply
  388. <https://git-scm.com/docs/git-apply>
  389. `git apply` permet d'appliquer un diff.
  390. On peut utiliser une option pour exclure l'application de certain fichier du diff :
  391. ~~~
  392. $ git apply --exclude=debian/changelog /tmp/foo.diff
  393. ~~~
  394. ### git blame
  395. <https://git-scm.com/docs/git-blame>
  396. Pour voir qui a modifié les lignes d'un fichier *foo/bar* :
  397. ~~~
  398. $ git blame foo/bar
  399. ~~~
  400. ### git revert
  401. <https://git-scm.com/docs/git-revert>
  402. Pour effectuer les modifications inverses de celles effectuées (et donc revenir à l'état précédent :
  403. ~~~
  404. $ git revert <SHA1 du commit>
  405. ~~~
  406. ### git tag
  407. Ajouter et pousser un tag à l'endroit où l'on est :
  408. ~~~
  409. $ git tag -a foo -m "version foo"
  410. $ git push origin foo
  411. ~~~
  412. Lister les tags :
  413. ~~~
  414. $ git tag
  415. foo
  416. ~~~
  417. Changer un tag foo en bar sur un dépôt distant :
  418. ~~~
  419. $ git co foo && git tag bar && git tag -d foo && git push origin :foo && git push --tags
  420. ~~~
  421. ### .git/config
  422. <https://git-scm.com/docs/git-config>
  423. La configuration d'un dépôt se trouve dans le fichier `.git/config`
  424. On peut éditer ce fichier ou utiliser des commandes pour le faire.
  425. Pour ajouter un dépôt distant :
  426. ~~~
  427. $ git remote add origin2 ssh://git.example.com/path/projet.git
  428. ~~~
  429. Pour lister les dépôts distants configurés :
  430. ~~~
  431. $ git remote
  432. ~~~
  433. ### Échanger des commits sous forme de patchs Git
  434. Pour transmettre ses 3 derniers commits, on peut générer 3 patches qui contiendront les diffs ainsi que les messages de commit :
  435. ~~~
  436. $ git format-patch -3
  437. ~~~
  438. Si l'on a ces 3 patches, on peut les appliquer sur son dépôt local ainsi :
  439. ~~~
  440. $ git am 000*.patch
  441. ~~~
  442. ### hooks
  443. On peut gérer des hooks à différents moments (pre-commit, post-commit, pre-push, post-push, etc.),
  444. par exemple pour générer des emails de notification.
  445. Voir dans le répertoire `.git/hooks/`.
  446. On peut par exemple s'en servir pour [activer des mails de commit](#mettre-en-place-des-notifications-de-push)
  447. ### dépôt « bare »
  448. Un dépôt classique possède un répertoire `.git/` qui contient toutes les données et méta-données, ainsi qu'une *working copy* de la branche courante.
  449. Quand on crée un dépôt ayant vocation à servir de dépôt central, il est préférable de ne pas avoir de *working copy* : il s'agira alors d'un **bare repository** que l'on peut initier avec la commande :
  450. ~~~
  451. $ mkdir foo
  452. $ cd foo
  453. $ git init --bare
  454. ~~~
  455. ## Workflow de travail
  456. Il existe plusieurs workflows possibles en travaillant avec Git.
  457. ### Le modèle Git branching
  458. Voir <http://nvie.com/posts/a-successful-git-branching-model/>
  459. L'idée est de ne jamais toucher à *master*, sauf hotfixes. Pour le reste on le fait dans *dev*.
  460. Et pour les grosses features on le fait dans une branche, nommée avec le nom de la feature.
  461. ## Plomberie
  462. <https://git-scm.com/book/fr/Git-Commands-Plumbing-Commands>
  463. La plomberie de Git consiste à réaliser des commandes bas niveau
  464. manipulant tout ce qui se trouve dans le répertoire `.git/` d'un dépôt.
  465. Les données brutes sont dans le répertoire `.git/objects/` qui contient
  466. de nombreux fichiers : à chaque commit correspond un fichier nommé en fonction
  467. de l'empreinte SHA1 du commit et contenant les données compressées.
  468. Les données comprennent notamment la référence au(x) commit(s) *parent*
  469. ce qui permet d’avoir des liens entre les commits.
  470. Observons `.git/refs/` qui contient des pseudos-pointeurs (fichier texte d'une seule ligne contenant un SHA1 ou une autre référence) :
  471. * un tag est simplement un pointeur vers un commit ;
  472. * une branche est également un pointeur vers un commit, la différence est qu'il se déplace à chaque nouveau commit dans la branche.
  473. Directement dans `.git/` on a également *HEAD* (et *FETCH_HEAD*, *ORIG_HEAD*) qui sont aussi des pseudo-pointeurs, qui changent notamment quand on change de branche ou pendant un *rebase*.
  474. Si l'on veut mettre à jour ces pseudo-pointeurs, il faut utiliser `git update-ref`.
  475. Observons `.git/logs/` qui contient l'historique de ce qui a été fait dans le dépôt.
  476. Cet historique est notamment accessible avec la commande `git reflog`.
  477. ## FAQ
  478. ### Partager un dépôt en HTTP - simplement
  479. [https://www.kernel.org/pub/software/scm/git/docs/git-http-backend.html](https://www.kernel.org/pub/software/scm/git/docs/git-http-backend.html)
  480. Le dépôt git est dans /home/git/projets/projet.git, et le serveur web est Apache2.4.
  481. ~~~{.bash}
  482. SetEnv GIT_PROJECT_ROOT /home/git/
  483. SetEnv GIT_HTTP_EXPORT_ALL
  484. ScriptAlias /git/ /usr/lib/git-core/git-http-backend/
  485. Alias /git /home/git/projets
  486. <Location /git>
  487. AuthType Basic
  488. AuthName "Git HTTP Access"
  489. AuthUserFile /etc/apache2/htpasswd_git
  490. Require user git
  491. </Location>
  492. ~~~
  493. Pour cloner le dépot :
  494. ~~~{.bash}
  495. $ git clone http://git@domain:port/git/projet
  496. ~~~
  497. ### Partager un dépôt avec plusieurs utilisateurs
  498. Avec un dépôt *foo* existant, on autorisera les utilisateurs que s’ils appartiennent au groupe *git* :
  499. ~~~
  500. # cd foo
  501. # git config core.sharedRepository group
  502. # addgroup git
  503. # chgrp -R git .
  504. # chmod g=rwXs,o= -R .
  505. # chmod g=rwX -R . # astuce pour garder le +s sur les répertoires
  506. ~~~
  507. ### Importer un dépôt SVN dans GIT
  508. Ce script permet de récupérer la liste des auteurs SVN, modifiez-la comme voulu.
  509. ~~~{.bash}
  510. #!/usr/bin/env bash
  511. authors=$(svn log -q | grep -e '^r' | awk 'BEGIN { FS = "|" } ; { print $2 }' | sort | uniq)
  512. for author in ${authors}; do
  513. echo "${author} = Prenom Nom <jdoe@example.com>";
  514. done
  515. ~~~
  516. On lance ensuite la commande suivante :
  517. ~~~
  518. $ git svn --authors-file=path/to/authors_file clone svn+ssh://svn.example.com/path/to/repo
  519. ~~~
  520. ### Importer un dépôt CVS dans GIT
  521. Lancer la commande suivante :
  522. ~~~
  523. $ git cvsimport -C repo_git -r cvs -k -vA path/to/authors_file -d user@hostname:/path/to/cvsroot repo
  524. ~~~
  525. ### Importer un dépôt Arch dans GIT
  526. Lancer la commande suivante :
  527. ~~~
  528. $ git-archimport -v foo@arch.example.com--branch
  529. ~~~
  530. ### Convertir un dépôt en utf8
  531. Créer un fichier exécutable dans `/tmp/recode-all-files` :
  532. ~~~{.bash}
  533. #!/bin/sh
  534. find . -type f -print | while read f; do
  535. mv -i "$f" "$f.recode.$$"
  536. iconv -f iso-8859-1 -t utf-8 < "$f.recode.$$" > "$f"
  537. rm -f "$f.recode.$$"
  538. done
  539. ~~~
  540. Puis exécuter la commande suivante dans votre dépôt :
  541. ~~~
  542. $ git filter-branch --tree-filter /tmp/recode-all-files HEAD
  543. ~~~
  544. Exécuter ensuite la commande suivante pour convertir les messages de commit :
  545. ~~~
  546. $ git filter-branch --msg-filter 'iconv -f iso-8859-1 -t utf-8' -- --all
  547. ~~~
  548. ### Push vers un non-bare repository
  549. Ceci est évidemment déconseillé, car cela mettra aussi à jour les fichiers, ce qui nécessite
  550. de faire un `git reset --hard`. Mais si l'on veut tout de même le forcer :
  551. ~~~
  552. $ git push
  553. Counting objects: 7, done.
  554. Delta compression using up to 4 threads.
  555. Compressing objects: 100% (4/4), done.
  556. Writing objects: 100% (4/4), 618 bytes, done.
  557. Total 4 (delta 3), reused 0 (delta 0)
  558. Unpacking objects: 100% (4/4), done.
  559. remote: error: refusing to update checked out branch: refs/heads/master
  560. remote: error: By default, updating the current branch in a non-bare repository
  561. remote: error: is denied, because it will make the index and work tree inconsistent
  562. remote: error: with what you pushed, and will require 'git reset --hard' to match
  563. remote: error: the work tree to HEAD.
  564. remote: error:
  565. remote: error: You can set 'receive.denyCurrentBranch' configuration variable to
  566. remote: error: 'ignore' or 'warn' in the remote repository to allow pushing into
  567. remote: error: its current branch; however, this is not recommended unless you
  568. remote: error: arranged to update its work tree to match what you pushed in some
  569. remote: error: other way.
  570. remote: error:
  571. remote: error: To squelch this message and still keep the default behaviour, set
  572. remote: error: 'receive.denyCurrentBranch' configuration variable to 'refuse'.
  573. ! [remote rejected] master -> master (branch is currently checked out)
  574. ~~~
  575. Il faut ajouter dans la config du repository « distant » :
  576. ~~~
  577. [receive]
  578. denyCurrentBranch = warn
  579. ~~~
  580. ### Transformer un non-bare repository en bare repository
  581. Il suffit de supprimer tous les fichiers sauf le `.git`, par exemple :
  582. ~~~
  583. $ rm -rf *
  584. ~~~
  585. Puis d'indiquer dans la config du repository :
  586. ~~~
  587. bare = true
  588. ~~~
  589. ### Mettre en place des notifications de push
  590. Sous Debian, pour envoyer des notifications par email à git@example.com :
  591. ~~~
  592. # chmod a+x /usr/share/doc/git-core/contrib/hooks/post-receive-email
  593. $ cd /path/path/to/your/repository.git
  594. $ ln -sf /usr/share/doc/git-core/contrib/hooks/post-receive-email hooks/post-receive
  595. $ git hooks.mailinglist git@example.com
  596. ~~~
  597. Pour recevoir les patches :
  598. ~~~
  599. $ git config hooks.showrev "git show -C %s; echo
  600. ~~~
  601. ### Ignorer les vérifications SSL
  602. (à éviter autant que possible bien sûr)
  603. ~~~
  604. $ git config --global http.sslverify "false"
  605. ~~~
  606. ### Nettoyage d'un dépôt Git
  607. Quand on supprime des commits, ils ne sont pas vraiment supprimés du dépôt.
  608. Cela offre l'avantage de pouvoir les retrouver en cas de besoin.
  609. Si l'on veut gagner de la place, on peut aussi faire un nettoyage :
  610. ~~~
  611. $ git repack
  612. $ git gc
  613. ~~~
  614. ### Migrer un dépot git
  615. Il se peut qu'on change de forge (passage de gitolite à gitlab par
  616. exemple) et il faut alors migrer les dépots. Un moyen de faire :
  617. ~~~{.bash}
  618. $ for branch in `git branch -a | grep remotes | grep -v HEAD | grep -v master`; do rbranch=$(echo $branch | tr '/' ' ' | awk '{print $3}') ; git checkout -b $rbranch $branch ; done
  619. $ git remote add gitlab gitlab@gitlab.example.com:group/repo.git && git push gitlab --all && git remote remove origin && git remote rename gitlab origin && git push --set-upstream origin master
  620. ~~~
  621. ### Avoir des stats basiques
  622. Il existe la commande shortlog pour avoir quelques stats sur un dépôt git
  623. ~~~
  624. $ git shortlog -sne
  625. ~~~
  626. ### Supprimer un fichier du dépôt et non en local
  627. ~~~
  628. $ git rm --cached file
  629. ~~~
  630. ### Supprimer le dernier commit
  631. À faire avec précaution bien sûr :
  632. ~~~
  633. $ git reset --hard HEAD^
  634. ~~~
  635. ### Troubleshooting bitbucket
  636. Si soucis avec Bitbucket, notamment performance réseau, on peut tester :
  637. ~~~
  638. $ git clone https://bitbucket.org/mirror/git.git
  639. ~~~
  640. [Notamment Bitbucket a des performances mauvaises (ou nulles) en IPv6.](https://grosse.io/blog/posts/Fixing-slow-Bitbucket-git-connections-via-SSH)
  641. Voir <https://confluence.atlassian.com/bbkb/troubleshooting-network-issues-389778693.html>
  642. ### Algorithme de diff
  643. Un diff peut être présenté de différentes façons.
  644. Exemple très simple, si le fichier original est :
  645. ~~~
  646. [foo]
  647. A
  648. ~~~
  649. et le fichier modifié est :
  650. ~~~
  651. [bar]
  652. A
  653. ~~~
  654. Le diff peut être :
  655. ~~~
  656. -[foo]
  657. +[bar]
  658. ~~~
  659. ou :
  660. ~~~
  661. -[foo]
  662. -A
  663. +[bar]
  664. +A
  665. ~~~
  666. …évidemment cet exemple très simple est juste pour démontrer qu'il peut y avoir des diffs différents pour une même modification.
  667. Ainsi, on peut utiliser différents algorithmes de diff avec `git diff` ou `git show` : minimal, patience, histogram ou myers.
  668. ~~~
  669. $ git diff --minimal
  670. $ git diff --patience
  671. $ git diff --histogram
  672. $ git diff --diff-algorithm=myers
  673. ~~~
  674. ### alias
  675. Voici des alias qui peuvent être intéressants :
  676. ~~~
  677. d = diff --ignore-space-change --patience --no-prefix
  678. # affiche le diff en mode "patience", sans les changements d'espaces et sans les prefix
  679. dw = diff --word-diff
  680. # affiche le diff en mode "word" qui met en évidence les changements au sein de chaque ligne
  681. lg = log --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit --date=relative
  682. # log des commits affichés avec une présentation riche mais compacte
  683. cane = commit --amend --no-edit
  684. # modifie le dernier commit sans éditer le message de commit
  685. rf = !sh -c 'rm $1 && git checkout $1'
  686. # restaure un fichier/emplacement depuis le dépôt
  687. s = status --short --branch
  688. # affiche un statut compacte
  689. conflicts = !sh -c 'git status -sb | grep ^UU | sed "s/UU\\ //"'
  690. # liste les fichiers ayant un conflit non résolu
  691. resolve = !sh -c 'git conflicts && $EDITOR $(git conflicts) +\"/<<<<\"'
  692. # ouvre les fichiers en conflit dans un éditeur (compatible Vim), positionné au bon endroit
  693. ~~~
  694. ### Quitter l'éditeur de texte sans que Git n'exécute l'action liée
  695. Lorsque Git délègue à l'éditeur de texte la rédaction du message de commit (ou autre édition), si l'éditeur quitte avec un code de sortie 0, alors Git considère que tout va bien et exécute son action initiale (faire un commit par exemple). Si on veut que Git ne fasse pas cette action, il suffit de faire quitter l'éditeur avec un code de sortie > 0. Avec Vim, ça se fait avec la commande `:cq`.
  696. Exemple concret de cette situation : on veut amender un commit auquel on a ajouté (ou retiré) certains éléments, mais au moment de rédiger le message on se rend compte qu'on en a trop ajouté (ou retiré). Un simple `:q!` dans Vim ne validera pas le message de commit mais validera le commit lui-même. C'est là qu'on peut sortir de Vim et annuler l'action de Git avec `:cq`.