Skip to content

Latest commit

 

History

History
802 lines (631 loc) · 39.4 KB

File metadata and controls

802 lines (631 loc) · 39.4 KB

Contribuir a un Projecte

La principal dificultat en descriure com contribuir a un projecte són les nombroses variacions sobre com fer-ho. Com que Git és molt flexible, la gent pot i treballa junta de moltes maneres, i és problemàtic descriure com hauríeu de contribuir: cada projecte és una mica diferent. Algunes de les variables involucrades són el nombre de contribuïdors actius, el flux de treball triat, el vostre accés de commit, i possiblement el mètode de contribució externa.

La primera variable és el nombre de contribuïdors actius: quants usuaris estan contribuint activament codi a aquest projecte, i amb quina freqüència? En moltes instàncies, tindreu dos o tres desenvolupadors amb uns quants commits al dia, o possiblement menys per a projectes una mica dormits. Per a empreses o projectes més grans, el nombre de desenvolupadors podria ser de milers, amb centenars o milers de commits arribant cada dia. Això és important perquè amb més i més desenvolupadors, us trobareu amb més problemes per assegurar-vos que el vostre codi s’aplica netament o es pot fusionar fàcilment. Els canvis que envieu poden ser declarats obsolets o severament trencats per la feina que es fusiona mentre esteu treballant o mentre els vostres canvis esperen ser aprovats o aplicats. Com podeu mantenir el vostre codi consistentment actualitzat i els vostres commits vàlids?

La següent variable és el flux de treball en ús per al projecte. És centralitzat, amb cada desenvolupador tenint accés d’escriptura igual a la línia de codi principal? Té el projecte un mantenedor o gestor d’integració que revisa tots els parxos? Són tots els parxos revisats i aprovats pels companys? Esteu involucrat en aquest procés? Està en funcionament un sistema de tinents, i heu de presentar la vostra feina a ells primer?

La següent variable és el vostre accés de commit. El flux de treball requerit per contribuir a un projecte és molt diferent si teniu accés d’escriptura al projecte que si no. Si no teniu accés d’escriptura, com prefereix el projecte acceptar la feina contribuïda? Té alguna política? Quanta feina esteu contribuint a la vegada? Amb quina freqüència contribuïu?

Totes aquestes preguntes poden afectar com contribuïu de manera efectiva a un projecte i quins fluxos de treball són preferits o disponibles per a vosaltres. Tractarem aspectes de cadascun d’aquests en una sèrie de casos d’ús, passant de senzills a més complexos; hauríeu de poder construir els fluxos de treball específics que necessiteu en la pràctica a partir d’aquests exemples.

Directrius per als Commits

Abans de començar a veure els casos d’ús específics, aquí teniu una nota ràpida sobre els missatges de commit. Tindre una bona guia per crear commits i seguir-la fa que treballar amb Git i col·laborar amb altres sigui molt més fàcil. El projecte Git proporciona un document que estableix una sèrie de bons consells per crear commits a partir dels quals enviar parxos: podeu llegir-lo al codi font de Git al fitxer Documentation/SubmittingPatches.

Primer, les vostres presentacions no haurien de contenir cap error d’espai en blanc. Git proporciona una manera fàcil de comprovar això: abans de fer commit, executeu git diff --check, que identifica possibles errors d’espai en blanc i els llista per a vosaltres.

Sortida de `git diff --check`
Figure 1. Sortida de git diff --check

Si executeu aquesta ordre abans de fer commit, podeu veure si esteu a punt de fer commit d’errors d’espai en blanc que podrien molestar altres desenvolupadors.

A continuació, intenteu fer que cada commit sigui un conjunt de canvis lògicament separat. Si podeu, intenteu fer que els vostres canvis siguin digeribles: no codeu tot un cap de setmana en cinc problemes diferents i després envieu-los tots com un commit massiu el dilluns. Fins i tot si no feu commit durant el cap de setmana, utilitzeu l’àrea de preparació el dilluns per dividir la vostra feina en almenys un commit per problema, amb un missatge útil per commit. Si alguns dels canvis modifiquen el mateix fitxer, intenteu utilitzar git add --patch per preparar parcialment fitxers (cobert en detall a ch07-git-tools.asc). L’instantani del projecte a la punta de la branca és idèntic ja sigui que feu un commit o cinc, sempre que tots els canvis s’afegeixin en algun moment, així que intenteu fer les coses més fàcils als vostres companys desenvolupadors quan hagin de revisar els vostres canvis.

Aquest enfocament també fa que sigui més fàcil treure o revertir un dels conjunts de canvis si ho necessiteu més endavant. ch07-git-tools.asc descriu una sèrie de trucs útils de Git per reescriure la història i preparar fitxers de manera interactiva: utilitzeu aquestes eines per ajudar a elaborar una història neta i comprensible abans d’enviar la feina a algú altre.

L’última cosa a tenir en compte és el missatge de commit. Acostumar-se a crear missatges de commit de qualitat fa que utilitzar i col·laborar amb Git sigui molt més fàcil. Com a regla general, els vostres missatges haurien de començar amb una única línia que no sigui més llarga d’uns 50 caràcters i que descriu el conjunt de canvis de manera concisa, seguida d’una línia en blanc, seguida d’una explicació més detallada. El projecte Git requereix que l’explicació més detallada inclogui la vostra motivació per al canvi i contrasti la seva implementació amb el comportament anterior: aquesta és una bona guia a seguir. Escriviu el vostre missatge de commit en imperatiu: "Corregeix l’error" i no "Corregit l’error" o "Correccions de l’error". Aquí teniu una plantilla que podeu seguir, que hem adaptat lleugerament d’una originalment escrita per Tim Pope:

Resum capitalitzat, curt (50 caràcters o menys)

Text explicatiu més detallat, si és necessari. Enrotlleu-lo a uns 72
caràcters o així. En alguns contextos, la primera línia es tracta com el
assumpte d'un correu electrònic i la resta del text com el cos. La línia
en blanc que separa el resum del cos és crítica (a menys que ometeu
el cos completament); eines com rebase us confondran si executeu
els dos junts.

Escriviu el vostre missatge de commit en imperatiu: "Corregeix l'error" i no "Corregit l'error"
o "Correccions de l'error." Aquesta convenció coincideix amb els missatges de commit generats
per ordres com git merge i git revert.

Els paràgrafs addicionals venen després de línies en blanc.

- Els punts de la llista també estan bé

- Generalment s'utilitza un guió o un asterisc per al punt, seguit d'un
  espai únic, amb línies en blanc entre ells, però les convencions varien aquí

- Utilitzeu una sangria penjada

Si tots els vostres missatges de commit segueixen aquest model, les coses seran molt més fàcils per a vosaltres i els desenvolupadors amb els quals col·laboreu. El projecte Git té missatges de commit ben formatats: intenteu executar git log --no-merges per veure com és un historial de commits de projecte ben formatat.

Note
Feu com diem, no com fem.

Per raó de brevetat, molts dels exemples en aquest llibre no tenen missatges de commit ben formatats com aquest; en lloc d’això, simplement utilitzem l’opció -m a git commit.

En resum, feu com diem, no com fem.

Equip Privat Petit

La configuració més senzilla que és probable que us trobeu és un projecte privat amb un o dos altres desenvolupadors. "Privat", en aquest context, significa de codi tancat: no accessible al món exterior. Vosaltres i els altres desenvolupadors teniu accés de push al repositori.

En aquest entorn, podeu seguir un flux de treball similar al que podríeu fer quan utilitzeu Subversion o un altre sistema centralitzat. Encara obteniu els avantatges de coses com commits fora de línia i branques i fusions molt més senzilles, però el flux de treball pot ser molt similar; la principal diferència és que les fusions passen al costat del client en lloc de al servidor en el moment del commit. Veiem com podria ser quan dos desenvolupadors comencen a treballar junts amb un repositori compartit. El primer desenvolupador, John, clona el repositori, fa un canvi i fa commit localment. Els missatges del protocol s’han reemplaçat amb …​ en aquests exemples per escurçar-los una mica.

# Màquina de John
$ git clone john@githost:simplegit.git
Cloning into 'simplegit'...
...
$ cd simplegit/
$ vim lib/simplegit.rb
$ git commit -am 'Remove invalid default value'
[master 738ee87] Remove invalid default value
 1 files changed, 1 insertions(+), 1 deletions(-)

El segon desenvolupador, Jessica, fa el mateix: clona el repositori i fa commit d’un canvi:

# Màquina de Jessica
$ git clone jessica@githost:simplegit.git
Cloning into 'simplegit'...
...
$ cd simplegit/
$ vim TODO
$ git commit -am 'Add reset task'
[master fbff5bc] Add reset task
 1 files changed, 1 insertions(+), 0 deletions(-)

Ara, Jessica fa push de la seva feina al servidor, el qual funciona perfectament:

# Màquina de Jessica
\$ git push origin master
...
To jessica@githost:simplegit.git
   1edee6b..fbff5bc  master -> master

L’última línia de la sortida anterior mostra un missatge de retorn útil de l’operació de push. El format bàsic és <oldref>..<newref> fromref → toref, on oldref significa l’antiga referència, newref significa la nova referència, fromref és el nom de la referència local que s’està fent push, i toref és el nom de la referència remota que s’està actualitzant. Veureu sortides similars com aquesta a continuació en les discussions, així que tenir una idea bàsica del significat us ajudarà a entendre els diversos estats dels repositoris. Més detalls estan disponibles a la documentació de git-push.

Continuant amb aquest exemple, poc després, John fa alguns canvis, els fa commit al seu repositori local i intenta fer push al mateix servidor:

# Màquina de John
\$ git push origin master
To john@githost:simplegit.git
 ! [rejected]        master -> master (non-fast forward)
error: failed to push some refs to 'john@githost:simplegit.git'

En aquest cas, el push de John falla a causa del push anterior de Jessica dels seus canvis. Això és especialment important d’entendre si esteu acostumat a Subversion, perquè notareu que els dos desenvolupadors no van editar el mateix fitxer. Tot i que Subversion automàticament fa una fusió com aquesta al servidor si s’editen fitxers diferents, amb Git, heu de fusionar primer els commits localment. En altres paraules, John ha de fer primer fetch dels canvis de Jessica i fusionar-los al seu repositori local abans que se li permeti fer push.

Com a primer pas, John fa fetch de la feina de Jessica (això només fa fetch de la feina de Jessica, encara no la fusiona amb la feina de John):

$ git fetch origin
...
From john@githost:simplegit
 + 049d078...fbff5bc master     -> origin/master

En aquest punt, el repositori local de John sembla alguna cosa com això:

Historial divergent de John
Figure 2. Historial divergent de John

Ara John pot fusionar la feina de Jessica que ha fet fetch a la seva pròpia feina local:

$ git merge origin/master
Merge made by the 'recursive' strategy.
 TODO |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)

Sempre que aquesta fusió local vagi sense problemes, l’historial actualitzat de John ara semblarà això:

Repositori de John després de fusionar `origin/master`
Figure 3. Repositori de John després de fusionar origin/master

En aquest punt, John podria voler provar aquest nou codi per assegurar-se que cap de la feina de Jessica afecta cap de la seva i, sempre que tot sembli bé, finalment pot fer push de la nova feina fusionada al servidor:

\$ git push origin master
...
To john@githost:simplegit.git
   fbff5bc..72bbc59  master -> master

Al final, l’historial de commits de John semblarà això:

Historial de John després de fer push al servidor `origin`
Figure 4. Historial de John després de fer push al servidor origin

Mentrestant, Jessica ha creat una nova branca de tema anomenada issue54, i ha fet tres commits a aquesta branca. Ella encara no ha fet fetch dels canvis de John, així que el seu historial de commits sembla això:

Branca de tema de Jessica
Figure 5. Branca de tema de Jessica

De sobte, Jessica aprèn que John ha fet push de nova feina al servidor i ella vol donar un cop d’ull, així que pot fer fetch de tot el nou contingut del servidor que encara no té amb:

# Màquina de Jessica
\$ git fetch origin
...
From jessica@githost:simplegit
   fbff5bc..72bbc59  master     -> origin/master

Això baixa la feina que John ha fet push mentrestant. L’historial de Jessica ara sembla això:

Historial de Jessica després de fer fetch dels canvis de John
Figure 6. Historial de Jessica després de fer fetch dels canvis de John

Jessica pensa que la seva branca de tema està llesta, però vol saber quina part de la feina de John que ha fet fetch ha de fusionar a la seva feina perquè pugui fer push. Ella executa git log per descobrir-ho:

\$ git log --no-merges issue54..origin/master
commit 738ee872852dfaa9d6634e0dea7a324040193016
Author: John Smith <jsmith@example.com>
Date:   Fri May 29 16:01:27 2009 -0700

   Remove invalid default value

La sintaxi issue54..origin/master és un filtre de log que demana a Git que mostri només aquells commits que estan a la última branca (en aquest cas origin/master) i que no estan a la primera branca (en aquest cas issue54). Tractarem aquesta sintaxi en detall a ch07-git-tools.asc.

De la sortida anterior, podem veure que hi ha un únic commit que John ha fet i que Jessica no ha fusionat a la seva feina local. Si ella fusiona origin/master, aquest serà l’únic commit que modificarà la seva feina local.

Ara, Jessica pot fusionar la seva feina de tema a la seva branca master, fusionar la feina de John (origin/master) a la seva branca master, i després fer push al servidor una altra vegada.

Primer (havent fet commit de tota la feina a la seva branca de tema issue54), Jessica canvia de nou a la seva branca master en preparació per integrar tota aquesta feina:

\$ git checkout master
Switched to branch 'master'
Your branch is behind 'origin/master' by 2 commits, and can be fast-forwarded.

Jessica pot fusionar origin/master o issue54 primer: tots dos són upstream, així que l’ordre no importa. L’instantani final hauria de ser idèntic independentment de l’ordre que triï; només l’historial serà diferent. Ella tria fusionar la branca issue54 primer:

$ git merge issue54
Updating fbff5bc..4af4298
Fast forward
 README           |    1 +
 lib/simplegit.rb |    6 +++++-
 2 files changed, 6 insertions(+), 1 deletions(-)

No hi ha problemes; com podeu veure, va ser una fusió de fast-forward senzilla. Jessica completa ara el procés de fusió local fusionant la feina de John anteriorment fet fetch que es troba a la branca origin/master:

$ git merge origin/master
Auto-merging lib/simplegit.rb
Merge made by the 'recursive' strategy.
 lib/simplegit.rb |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

Tot es fusiona netament, i l’historial de Jessica ara sembla això:

Historial de Jessica després de fusionar els canvis de John
Figure 7. Historial de Jessica després de fusionar els canvis de John

Ara origin/master és accessible des de la branca master de Jessica, així que hauria de poder fer push amb èxit (assumint que John no ha fet push de més canvis mentrestant):

\$ git push origin master
...
To jessica@githost:simplegit.git
   72bbc59..8059c15  master -> master

Cada desenvolupador ha fet commit unes quantes vegades i ha fusionat la feina de l’altre amb èxit.

Historial de Jessica després de fer push de tots els canvis al servidor
Figure 8. Historial de Jessica després de fer push de tots els canvis al servidor

Això és un dels fluxos de treball més senzills. Treballes durant una estona (generalment en una branca de tema), i fusiones aquesta feina a la teva branca master quan està llesta per ser integrada. Quan vols compartir aquesta feina, fas fetch i fusiones el teu master des de origin/master si ha canviat, i finalment fas push a la branca master al servidor. La seqüència general és alguna cosa com això:

Seqüència general d’esdeveniments per a un flux de treball simple de múltiples desenvolupadors de Git
Figure 9. Seqüència general d’esdeveniments per a un flux de treball simple de múltiples desenvolupadors de Git

Equip Privat Gestionat

En aquest següent escenari, veureu els rols dels contribuïdors en un grup privat més gran. Aprendreu com treballar en un entorn on petits grups col·laboren en funcions, després de les quals aquestes contribucions basades en equips són integrades per una altra part.

Suposem que John i Jessica estan treballant junts en una funció (anomenem això “featureA”), mentre que Jessica i un tercer desenvolupador, Josie, estan treballant en una segona (digem, “featureB”). En aquest cas, l’empresa està utilitzant un tipus de flux de treball de gestor d’integració on la feina dels grups individuals és integrada només per certs enginyers, i la branca master del repositori principal només pot ser actualitzada per aquests enginyers. En aquest escenari, tota la feina es fa en branques basades en equips i es recull pels integradors més tard.

Seguim el flux de treball de Jessica mentre treballa en les seves dues funcions, col·laborant en paral·lel amb dos desenvolupadors diferents en aquest entorn. Suposant que ja té el seu repositori clonat, decideix treballar en featureA primer. Crea una nova branca per a la funció i fa alguna feina allà:

# Màquina de Jessica
\$ git checkout -b featureA
Switched to a new branch 'featureA'
$ vim lib/simplegit.rb
$ git commit -am 'Add limit to log function'
[featureA 3300904] Add limit to log function
 1 files changed, 1 insertions(+), 1 deletions(-)

En aquest punt, necessita compartir la seva feina amb John, així que fa push dels commits de la seva branca featureA al servidor. Jessica no té accés de push a la branca master: només els integradors ho tenen: així que ha de fer push a una altra branca per poder col·laborar amb John:

\$ git push -u origin featureA
...
To jessica@githost:simplegit.git
 * [new branch]      featureA -> featureA

Jessica envia un correu electrònic a John per dir-li que ha fet push de alguna feina a una branca anomenada featureA i que pot mirar-la ara. Mentrestant espera el feedback de John, Jessica decideix començar a treballar en featureB amb Josie. Per començar, inicia una nova branca de funció, basant-la en la branca master del servidor:

# Màquina de Jessica
\$ git fetch origin
$ git checkout -b featureB origin/master
Switched to a new branch 'featureB'

Ara, Jessica fa un parell de commits a la branca featureB:

$ vim lib/simplegit.rb
$ git commit -am 'Make ls-tree function recursive'
[featureB e5b0fdc] Make ls-tree function recursive
 1 files changed, 1 insertions(+), 1 deletions(-)
$ vim lib/simplegit.rb
$ git commit -am 'Add ls-files'
[featureB 8512791] Add ls-files
 1 files changed, 5 insertions(+), 0 deletions(-)

El repositori de Jessica ara sembla això:

Historial de commits inicial de Jessica
Figure 10. Historial de commits inicial de Jessica

Està llesta per fer push de la seva feina, però rep un correu electrònic de Josie que diu que una branca amb alguna feina inicial de “featureB” ja ha estat feta push al servidor com a branca featureBee. Jessica necessita fusionar aquests canvis amb els seus abans de poder fer push de la seva feina al servidor. Jessica primer fa fetch dels canvis de Josie amb git fetch:

$ git fetch origin
...
From jessica@githost:simplegit
 * [new branch]      featureBee -> origin/featureBee

Suposant que Jessica encara està a la seva branca featureB, ara pot fusionar la feina de Josie a aquesta branca amb git merge:

$ git merge origin/featureBee
Auto-merging lib/simplegit.rb
Merge made by the 'recursive' strategy.
 lib/simplegit.rb |    4 ++++
 1 files changed, 4 insertions(+), 0 deletions(-)

En aquest punt, Jessica vol fer push de tota aquesta feina fusionada de “featureB” al servidor, però no vol simplement fer push de la seva pròpia branca featureB. Més aviat, com que Josie ja ha començat una branca featureBee upstream, Jessica vol fer push a aquesta branca, el que fa amb:

$ git push -u origin featureB:featureBee
...
To jessica@githost:simplegit.git
   fba9af8..cd685d1  featureB -> featureBee

Això s’anomena un refspec. Vegeu ch10-git-internals.asc per a una discussió més detallada dels refspecs de Git i les diferents coses que podeu fer amb ells. També noteu la bandera -u: és curta per a --set-upstream, que configura les branques per a un push i pull més fàcils més endavant.

De sobte, Jessica rep un correu electrònic de John, que li diu que ha fet push de alguns canvis a la branca featureA en la qual estan col·laborant, i li demana a Jessica que hi doni un cop d’ull. Un altre cop, Jessica executa un simple git fetch per obtenir tot el nou contingut del servidor, incloent (per descomptat) la feina més recent de John:

$ git fetch origin
...
From jessica@githost:simplegit
   3300904..aad881d  featureA   -> origin/featureA

Jessica pot mostrar el log de la nova feina de John comparant el contingut de la branca featureA recentment fet fetch amb la seva còpia local de la mateixa branca:

$ git log featureA..origin/featureA
commit aad881d154acdaeb2b6b18ea0e827ed8a6d671e6
Author: John Smith <jsmith@example.com>
Date:   Fri May 29 19:57:33 2009 -0700

    Increase log output to 30 from 25

Si a Jessica li agrada el que veu, pot fusionar la nova feina de John a la seva branca local featureA amb:

$ git checkout featureA
Switched to branch 'featureA'
$ git merge origin/featureA
Updating 3300904..aad881d
Fast forward
 lib/simplegit.rb |   10 +++++++++-
1 files changed, 9 insertions(+), 1 deletions(-)

Finalment, Jessica podria voler fer un parell de canvis menors a tot aquest contingut fusionat, així que és lliure de fer aquests canvis, fer-los commit a la seva branca local featureA i fer push del resultat final al servidor:

$ git commit -am 'Add small tweak to merged content'
[featureA 774b3ed] Add small tweak to merged content
 1 files changed, 1 insertions(+), 1 deletions(-)
$ git push
...
To jessica@githost:simplegit.git
   3300904..774b3ed  featureA -> featureA

L’historial de commits de Jessica ara sembla alguna cosa com això:

Historial de Jessica després de fer commit a una branca de funció
Figure 11. Historial de Jessica després de fer commit a una branca de funció

En algun moment, Jessica, Josie i John informen als integradors que les branques featureA i featureBee al servidor estan llestes per a la integració a la línia principal. Després que els integradors fusionin aquestes branques a la línia principal, un fetch baixarà el nou commit de fusió, fent que l’historial sembli això:

Historial de Jessica després de fusionar les seves dues branques de tema
Figure 12. Historial de Jessica després de fusionar les seves dues branques de tema

Molts grups canvien a Git a causa d’aquesta capacitat de tenir múltiples equips treballant en paral·lel, fusionant les diferents línies de feina tard al procés. La capacitat de subgrups més petits d’un equip per col·laborar a través de branques remotes sense necessàriament haver d’involucrar o impedint tot l’equip és un gran benefici de Git. La seqüència per al flux de treball que heu vist aquí és alguna cosa com això:

Seqüència bàsica d’aquest flux de treball d’equip gestionat
Figure 13. Seqüència bàsica d’aquest flux de treball d’equip gestionat

Projecte Públic Bifurcat

Contribuir a projectes públics és una mica diferent. Com que no teniu els permisos per actualitzar directament les branques al projecte, heu de fer arribar la feina als mantenedors d’alguna altra manera. Aquest primer exemple descriu la contribució mitjançant bifurcació en hosts de Git que admeten bifurcació fàcil. Molts llocs d’allotjament admeten això (incloent GitHub, BitBucket, repo.or.cz, i altres), i molts mantenedors de projectes esperen aquest estil de contribució. La següent secció tracta projectes que prefereixen acceptar parxos contribuïts via correu electrònic.

Primer, probablement voldreu clonar el repositori principal, crear una branca de tema per a la sèrie de parxos que planegeu contribuir, i fer-hi la vostra feina. La seqüència sembla bàsicament així:

$ git clone <url>
$ cd project
$ git checkout -b featureA
  ... work ...
$ git commit
  ... work ...
\$ git commit
Note

Potser voldreu utilitzar rebase -i per aplanar la vostra feina a un únic commit, o reorganitzar la feina als commits per fer que el parxo sigui més fàcil de revisar per al mantenedor: vegeu ch07-git-tools.asc per a més informació sobre el rebase interactiu.

Quan la feina de la vostra branca està acabada i esteu llest per contribuir-la de nou als mantenedors, aneu a la pàgina del projecte original i feu clic al botó “Fork”, creant la vostra pròpia bifurcació escriptible del projecte. Llavors heu d’afegir aquesta URL de repositori com a nou remot del vostre repositori local; en aquest exemple, anem a anomenar-lo myfork:

\$ git remote add myfork <url>

Llavors heu de fer push de la vostra nova feina a aquest repositori. És més fàcil fer push de la branca de tema en la qual esteu treballant al vostre repositori bifurcat, en lloc de fusionar aquesta feina a la vostra branca master i fer push d’això. La raó és que si la vostra feina no és acceptada o es fa cherry-pick, no heu de rebobinar la vostra branca master (l’operació cherry-pick de Git es tracta amb més detall a ch05-distributed-git.asc). Si els mantenedors merge, rebase, o cherry-pick la vostra feina, finalment l’obtindreu de qualsevol manera mitjançant el pull des del seu repositori.

En qualsevol cas, podeu fer push de la vostra feina amb:

\$ git push -u myfork featureA

Un cop la vostra feina s’ha fet push al vostre bifurcació del repositori, heu de notificar als mantenedors del projecte original que teniu feina que us agradaria que fusionessin. Això sovint s’anomena una sol·licitud de pull, i generalment genereu una sol·licitud com aquesta ja sigui a través del lloc web: GitHub té el seu propi mecanisme de “Pull Request” que tractarem a ch06-github.asc, o podeu executar l’ordre git request-pull i enviar la sortida posterior per correu electrònic al mantenedor del projecte manualment.

L’ordre git request-pull pren la branca base a la qual voleu que es faci pull de la vostra branca de tema i la URL del repositori Git del qual voleu que facin pull, i produeix un resum de tots els canvis que esteu demanant que es facin pull. Per exemple, si Jessica vol enviar a John una sol·licitud de pull, i ha fet dos commits a la branca de tema que acaba de fer push, pot executar això:

\$ git request-pull origin/master myfork
The following changes since commit 1edee6b1d61823a2de3b09c160d7080b8d1b3a40:
Jessica Smith (1):
        Create new function

are available in the git repository at:

  https://githost/simplegit.git featureA

Jessica Smith (2):
      Add limit to log function
      Increase log output to 30 from 25

 lib/simplegit.rb |   10 +++++++++-
 1 files changed, 9 insertions(+), 1 deletions(-)

Aquesta sortida es pot enviar al mantenedor: li diu d’on es va bifurcar la feina, resumeix els commits, i identifica d’on es fa pull de la nova feina.

En un projecte per al qual no sou el mantenedor, generalment és més fàcil tenir una branca com master que sempre segueixi origin/master i fer la vostra feina en branques de tema que podeu descartar fàcilment si són rebutjades. Tindre els temes de feina aïllats en branques de tema també fa que sigui més fàcil per a vosaltres rebasejar la vostra feina si la punta del repositori principal s’ha mogut mentrestant i els vostres commits ja no s’apliquen netament. Per exemple, si voleu enviar un segon tema de feina al projecte, no continueu treballant a la branca de tema que acabeu de fer push: comenceu de nou des de la branca master del repositori principal:

$ git checkout -b featureB origin/master
  ... work ...
$ git commit
$ git push myfork featureB
$ git request-pull origin/master myfork
  ... email generated request pull to maintainer ...
$ git fetch origin

Ara, cadascun dels vostres temes està contingut dins d’un silo: similar a una cua de parxos, que podeu reescriure, rebasejar i modificar sense que els temes interfereixin o interdependin entre si, com això:

Historial de commits inicial amb feina de `featureB`
Figure 14. Historial de commits inicial amb feina de featureB

Suposem que el mantenedor del projecte ha fet pull d’un munt de parxos i ha provat la vostra primera branca, però ja no es fusiona netament. En aquest cas, podeu intentar rebasejar aquesta branca sobre origin/master, resoldre els conflictes per al mantenedor, i després tornar a enviar els vostres canvis:

$ git checkout featureA
$ git rebase origin/master
$ git push -f myfork featureA

Això reescriu el vostre historial per semblar ara com Historial de commits després de la feina de featureA.

Historial de commits després de la feina de `featureA`
Figure 15. Historial de commits després de la feina de featureA

Com que heu rebasejat la branca, heu d’especificar -f a l’ordre de push per poder reemplaçar la branca featureA al servidor amb un commit que no és un descendent d’ella. Una alternativa seria fer push d’aquesta nova feina a una branca diferent al servidor (potser anomenada featureAv2).

Veiem un altre escenari possible: el mantenedor ha mirat la feina a la vostra segona branca i li agrada el concepte però us agradaria que canviéssiu un detall d’implementació. Aprofitareu aquesta oportunitat per moure la feina per basar-la en la branca master actual del projecte. Comenceu una nova branca basada en la branca origin/master actual, aplaneu els canvis de featureB allà, resolgueu qualsevol conflicte, feu el canvi d’implementació, i després feu push d’això com una nova branca:

$ git checkout -b featureBv2 origin/master
$ git merge --squash featureB
  ... change implementation ...
$ git commit
$ git push myfork featureBv2

L’opció --squash pren tota la feina a la branca fusionada i l’aplana en un conjunt de canvis, produint l’estat del repositori com si hagués passat una fusió real, sense fer realment un commit de fusió. Això significa que el vostre futur commit tindrà només un pare i us permet introduir tots els canvis d’una altra branca i després fer més canvis abans de registrar el nou commit. També l’opció --no-commit pot ser útil per retardar el commit de fusió en cas del procés de fusió per defecte.

En aquest punt, podeu notificar al mantenedor que heu fet els canvis sol·licitats, i que pot trobar aquests canvis a la vostra branca featureBv2.

Historial de commits després de la feina de `featureBv2`
Figure 16. Historial de commits després de la feina de featureBv2

Projecte Públic per Correu Electrònic

Molts projectes tenen procediments establerts per acceptar parxos: heu de comprovar les regles específiques per a cada projecte, perquè varien. Com que hi ha diversos projectes més antics i grans que accepten parxos a través d’una llista de correu de desenvolupadors, tractarem un exemple d’això ara.

El flux de treball és similar al cas d’ús anterior: creeu branques de tema per a cada sèrie de parxos en la qual treballareu. La diferència és com els envieu al projecte. En lloc de bifurcar el projecte i fer push a la vostra pròpia versió escriptible, genereu versions per correu electrònic de cada sèrie de commits i els envieu per correu electrònic a la llista de correu de desenvolupadors:

$ git checkout -b topicA
  ... work ...
$ git commit
  ... work ...
$ git commit

Ara teniu dos commits que voleu enviar a la llista de correu. Utilitzeu git format-patch per generar els fitxers en format mbox que podeu enviar per correu electrònic a la llista: converteix cada commit en un missatge de correu electrònic amb la primera línia del missatge de commit com a assumpte i la resta del missatge més el parxo que el commit introdueix com a cos. El bonic d’això és que aplicar un parxo des d’un correu electrònic generat amb format-patch preserva tota la informació del commit correctament.

$ git format-patch -M origin/master
0001-add-limit-to-log-function.patch
0002-increase-log-output-to-30-from-25.patch

L’ordre format-patch imprimeix els noms dels fitxers de parxo que crea. L’opció -M diu a Git que busqui canvis de nom. Els fitxers acaben semblant a això:

\$ cat 0001-add-limit-to-log-function.patch
From 330090432754092d704da8e76ca5c05c198e71a8 Mon Sep 17 00:00:00 2001
From: Jessica Smith <jessica@example.com>
Date: Sun, 6 Apr 2008 10:17:23 -0700
Subject: [PATCH 1/2] Add limit to log function

Limit log functionality to the first 20

---
 lib/simplegit.rb |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/lib/simplegit.rb b/lib/simplegit.rb
index 76f47bc..f9815f1 100644
--- a/lib/simplegit.rb
+++ b/lib/simplegit.rb
@@ -14,7 +14,7 @@ class SimpleGit
   end

   def log(treeish = 'master')
-    command("git log #{treeish}")
+    command("git log -n 20 #{treeish}")
   end

   def ls_tree(treeish = 'master')
--
2.1.0

També podeu editar aquests fitxers de parxo per afegir més informació per a la llista de correu que no voleu que aparegui al missatge de commit. Si afegiu text entre la línia --- i l’inici del parxo (la línia diff --git), els desenvolupadors podran llegir-lo, però aquest contingut serà ignorat pel procés de parxos.

Per enviar això a una llista de correu, podeu enganxar el fitxer al vostre programa de correu electrònic o enviar-lo mitjançant un programa de línia d’ordres. Enganxar el text sovint causa problemes de format, especialment amb clients “més intel·ligents” que no preserven els salts de línia i altres espais en blanc de manera adequada. Afortunadament, Git proporciona una eina per ajudar-vos a enviar parxos ben formatats via IMAP, el qual pot ser més fàcil per a vosaltres. Demostrarem com enviar un parxo via Gmail, que resulta ser l’agent de correu que coneixem millor; podeu llegir instruccions detallades per a una sèrie de programes de correu al final del fitxer Documentation/SubmittingPatches esmentat anteriorment al codi font de Git.

Primer, heu de configurar la secció imap al vostre fitxer ~/.gitconfig. Podeu configurar cada valor separat amb una sèrie d’ordres git config, o podeu afegir-los manualment, però al final el vostre fitxer de configuració hauria de semblar alguna cosa com això:

[imap]
  folder = "[Gmail]/Drafts"
  host = imaps://imap.gmail.com
  user = user@gmail.com
  pass = YX]8g76G_2^sFbd
  port = 993
  sslverify = false

Si el vostre servidor IMAP no utilitza SSL, les dues últimes línies probablement no són necessàries, i el valor de host serà imap:// en lloc de imaps://. Quan això està configurat, podeu utilitzar git imap-send per col·locar la sèrie de parxos a la carpeta de Drafts del servidor IMAP especificat:

\$ cat *.patch |git imap-send
Resolving imap.gmail.com... ok
Connecting to [74.125.142.109]:993... ok
Logging in...
sending 2 messages
100% (2/2) done

En aquest punt, hauríeu de poder anar a la vostra carpeta de Drafts, canviar el camp "Per a" a la llista de correu a la qual esteu enviant el parxo, possiblement CC al mantenedor o la persona responsable d’aquesta secció, i enviar-lo.

També podeu enviar els parxos a través d’un servidor SMTP. Com abans, podeu configurar cada valor separat amb una sèrie d’ordres git config, o podeu afegir-los manualment a la secció sendemail al vostre fitxer ~/.gitconfig:

[sendemail]
  smtpencryption = tls
  smtpserver = smtp.gmail.com
  smtpuser = user@gmail.com
  smtpserverport = 587

Després d’això, podeu utilitzar git send-email per enviar els vostres parxos:

\$ git send-email *.patch
0001-add-limit-to-log-function.patch
0002-increase-log-output-to-30-from-25.patch
Who should the emails appear to be from? [Jessica Smith <jessica@example.com>]
Emails will be sent from: Jessica Smith <jessica@example.com>
Who should the emails be sent to? jessica@example.com
Message-ID to be used as In-Reply-To for the first email? y

Llavors, Git escup una muntanya d’informació de log semblant a això per a cada parxo que esteu enviant:

(mbox) Adding cc: Jessica Smith <jessica@example.com> from
  \line 'From: Jessica Smith <jessica@example.com>'
OK. Log says:
Sendmail: /usr/sbin/sendmail -i jessica@example.com
From: Jessica Smith <jessica@example.com>
To: jessica@example.com
Subject: [PATCH 1/2] Add limit to log function
Date: Sat, 30 May 2009 13:29:15 -0700
Message-Id: <1243715356-61726-1-git-send-email-jessica@example.com>
X-Mailer: git-send-email 1.6.2.rc1.20.g8c5b.dirty
In-Reply-To: <y>
References: <y>

Result: OK
Tip

Per a ajuda en la configuració del vostre sistema i correu electrònic, més consells i trucs, i una zona de proves per enviar un parxo de prova via correu electrònic, aneu a git-send-email.io.

Resum

En aquesta secció, hem tractat múltiples fluxos de treball, i hem parlat de les diferències entre treballar com a part d’un equip petit en projectes de codi tancat versus contribuir a un gran projecte públic. Sabeu comprovar errors d’espai en blanc abans de fer commit, i podeu escriure un gran missatge de commit. Heu après a formatar parxos, i enviar-los per correu electrònic a una llista de correu de desenvolupadors. També s’ha tractat la gestió de fusions en el context dels diferents fluxos de treball. Ara esteu ben preparats per col·laborar en qualsevol projecte.

A continuació, veureu com treballar l’altra cara de la moneda: mantenir un projecte Git. Aprendreu com ser un dictador benevolent o gestor d’integració.