Kiel Mi Ruliĝas per Gito

Esperanto ▪ English
la 26-an de Julio 2019
Laste ĝisdatigita: la 11-an de Oktobro 2019

Male, tiuj kun senĉeseco povas malatenti kiujn aliaj pensas. Ion ajn ili povas fari en ilia propra mondo senzorgeme al la opinioj de tiuj ĉirkaŭ ili.
―Daigo UMEHARA

Enhavotabelo

Superrigardo

En mia ilaro estas terminalsimulilo, ŝelo, redaktilo, retumilo, kompililo, kaj gito. Ekde kiam giton mi konis antaŭ multaj jaroj, ĝi fariĝis unu el miaj plej uzataj iloj. Pro ĝia rapideco kaj amplekso de uzo, ĝin mi uzas kiel mia tria brako.

Pro tio ke emakson mi uzas, na Magit mi ankaŭ havas. Tamen, en ĉi tiu artikolo mi parolos pri kiel giton mi uzas ĉiutage sur la komandlinio.

La komandoj kaj funckioj kiujn ni havos ĉi tie estas por Ziŝo kaj Baŝo. Eblas, ke ili ankaŭ povas funkcii sur aliaj ŝeloj, tamen, ilin mi ne testis.

Mallongaj komandoj

Per gito, se la staton de deponejo ni volas vidi, la jenan komandon ni plenumos:

git status

Tamen, estas pluraj kazoj kiam pli mallongan version ni deziras uzi:

git s

La pli mallongan version ni uzas eble aŭ por la ŝparado de maŝinskribado aŭ estas fizike malfacilas por la plenan komandon maŝinskribi. En ĉi tiu sekcio mi diskutos pri la ekzistantaj metodoj por pli mallongajn komandojn fari.

Alinomoj

Manierojn por la difinado de mallongaj komandoj gito jam havas. Ekzemple, se ni deziras, ke anstataŭ

git clone

ni uzas je

git c

alinomon por la clone-komando ni povas difini per la alinoma sistemo de gito. Tion ni povas fari per du metodoj.

La unua metodo estas rekte per la komandlinio:

git config --global alias.c clone

La dua metodo estas per la agorda dosiero, kiu troviĝas en ~/.gitconfig. La jenan tekston ni metu en tiun dosieron:

[alias]
  c = clone

Arbitrajn komandojn oni ankaŭ povas uzi ene la alias-klaŭzo. Estas du metodoj por tion fari.

La unua metodo estas rekte kiel ŝela komando:

[alias]
  hello = "! echo hello world"

Se la komandon

git hello

oni plenumas, ŝajnos, ke la jenan komandon oni plenumis:

echo hello world

Do, konsekvece la eligo estas

hello world

La dua metodo estas per la difinado de ŝelaj funkcioj:

[alias]
  hi = "! hi () { echo hi world; }; hi"

Se la komandon

git hi

oni plenumas, ŝajnos, ke la jenan komandon oni plenumos:

hi () { echo hi world; }
hi

Per ĝi, ŝelan funkcion kiu nomiĝas hi oni unue difinis. Sekve, tiun funkcion ni vokis. Do, la eligo estas:

hi world

Alternativo

Dum tiuj metodoj bonas por multaj uzantoj, ili ne sufiĉas por mi tial, ke aliron al mia tuta ŝela agordo ĝi ne havas. Aliajn funkciojn kiujn mi havas en mia ŝelagordo ĝi ne povas voki. Pli grave, la funkciado per alinomoj estas limigita nur ene la medio de la gitagordo.

Kion mi uzas anstataŭe estas ke ŝelan funkcion mi difinis, en kiu, ilin mi povas voki per falsaj alinomoj kaj per validaj gitkomandoj. Per tiu sistemo, se la jenan komandon mi uzos:

git clone

Gito kondutas same kiel la originala komando. Tamen se la jenan komandon mi uzos:

git abc

la subkomandon abc, kiun mi difinis, vi vokos. Eĉ se alinomon kun sama nomo mi jam havas en ~/.gitconfig, ĉi tiu komando kuras per pli alta prioritato.

Agordo

En ĉi tiu sekcio estas difinoj kiujn ni devas meti en la agorddosiero de Ziŝo kaj Baŝo. Ilin mi havas en ~/.zshenv kaj ~/.bashrc, respektive.

Baza funkcio

Jen la baza funcio:

function git () {
  local git= self= op=

  if [[ -n "${BASH}" ]]; then
    git=$(which git)
    self=${FUNCNAME}
  elif [[ -n "${ZSH_NAME}" ]]; then
    git=$(whence -p git)
    self=$0
  else
    echo "Meh"
    return 1
  fi

  if [[ $# -eq 0 ]]; then
    if [[ -n "${BASH}" ]]; then
      type "${self}" | less
    elif [[ -n "${ZSH_NAME}" ]]; then
      which "${self}" | less
    else
      echo "Meh"
      return 1
    fi
  else
    op="$1"
    shift

    case "${op}" in
      # komandoj ĉi tie
      (*) =git "${op}" "[email protected]" ;;
    esac
  fi
}

Se ne estas komando por gito:

git

la difinon de la funkcio mem la ŝelo montras.

La subkomandoj loĝos en la areo markita # komandoj ĉi tie. La retropaŝa ago markita per * signifas, ke se ne estas propra komando el mi, la internan komandon de gito plenumi anstataŭ.

Gravaj komandoj

Jen la plej gravaj komandoj kiujn ni unue devas havi.

Ĉefaj operacioj

      (s) "${git}" status ;;
      (c) "${git}" clone "[email protected]" ;;
      (h) "${git}" show "[email protected]" ;;
      (mv) "${git}" mv "[email protected]" ;;
      (mv!) "${git}" mv -f "[email protected]" ;;
      (me) "${git}" merge "[email protected]" ;;
      (ta) "${git}" tag "[email protected]" ;;
      (bl) "${git}" blame "[email protected]" ;;

      (a) "${git}" add "[email protected]" ;;
      (au) "${self}" a -u ;;
      (a.) "${self}" a . ;;

      (ci) "${git}" commit "[email protected]" ;;
      (cia) "${self}" ci --amend "[email protected]" ;;
      (cim) "${self}" ci --message "[email protected]" ;;

      (co) "${git}" checkout "[email protected]" ;;
      (com) "${self}" co master ;;
      (cot) "${self}" co trunk ;;
      (co!) "${self}" co --force "[email protected]" ;;
      (cob) "${self}" co -b "[email protected]" ;;

      (rt) "${git}" reset "[email protected]" ;;
      (rt!) "${self}" rt --hard "[email protected]" ;;
      (rv) "${git}" revert "[email protected]" ;;

      (g) "${git}" grep "[email protected]" ;;
      (gi) "${self}" g -i "[email protected]" ;;

      (f) "${git}" fetch "[email protected]" ;;
      (fa) "${self}" f --all "[email protected]" ;;

      (rm) "${git}" rm "[email protected]" ;;
      (rmr) "${self}" rm -r "[email protected]" ;;
      (rm!) "${self}" rm -rf "[email protected]" ;;

Puŝado kaj tirado

      (ph) "${git}" push "[email protected]" ;;
      (phu) "${self}" ph -u "[email protected]" ;;
      (ph!) "${self}" ph --force "[email protected]" ;;
      (pho) "${self}" phu origin "[email protected]" ;;
      (phom) "${self}" pho master "[email protected]" ;;

      (pl) "${git}" pull "[email protected]" ;;
      (pl!) "${self}" pl --force "[email protected]" ;;
      (plr) "${self}" pl --rebase "[email protected]" ;;
      (plro) "${self}" plr origin "[email protected]" ;;
      (plru) "${self}" plr upstream "[email protected]" ;;
      (plrom) "${self}" plro master ;;
      (plrum) "${self}" plru master ;;
      (plrot) "${self}" plro trunk ;;
      (plrut) "${self}" plru trunk ;;

Branĉoj kaj dosierdiferencoj

      (br) "${git}" branch "[email protected]" ;;
      (bra) "${self}" br -a ;;
      (brh) "${git}" rev-parse --abbrev-ref HEAD ;;
      (brm) "${self}" br -m "[email protected]" ;;
      (brmh) "${self}" brm "$(git brh)" ;;
      (brd) "${self}" br -d "[email protected]" ;;
      (brD) "${self}" br -D "[email protected]" ;;

      (d) "${git}" diff "[email protected]" ;;
      (dc) "${git}" diff --cached "[email protected]" ;;
      (dh) "${self}" d HEAD ;;
      (dhw) "${self}" d --word-diff=color ;;

Protokoloj

      (l) "${git}" log "[email protected]" ;;
      (l1) "${self}" l -1 --pretty=%B ;;
      (lo) "${self}" l --oneline ;;
      (lp) "${self}" l --patch ;;
      (lp1) "${self}" lp -1 ;;
      (lpw) "${self}" lp --word-diff=color ;;

Aliaj komandoj

Jen aliaj komandoj kiujn ni ankaŭ devas difini.

Pravaloriziĝado kaj puŝadheloj

      (i) touch .gitignore; "${git}" init; "${self}" a.; "${self}" cim "[email protected]" ;;
      (oo) "${self}" ph origin "$(git brh)" ;;
      (oo!) "${self}" ph! origin "$(git brh)" ;;

Kiam ajn novajn deponejon mi kreas, la jenan komandon mi plenumas:

git i Pravaloriziĝu

Kion la oo subkomando faras estas ke la kodo puŝiĝos al la fordeponejo kiu nomiĝas origin sub la nomo de la aktuala branĉo. Ekzemple, se la aktuala branĉo nomiĝas trunk, kaj la jenan komandon oni plenumas:

git oo

la komando fariĝos

git ph origin trunk

Ŝanĝado de arboj

      (rb) "${git}" rebase "[email protected]" ;;
      (rbi) "${self}" rb --interactive "[email protected]" ;;
      (rbc) "${self}" rb --continue "[email protected]" ;;
      (rbs) "${self}" rb --skip "[email protected]" ;;
      (rba) "${self}" rb --abort "[email protected]" ;;
      (rbs) "${self}" rb --skip "[email protected]" ;;
      (rbi!) "${self}" rbi --root "[email protected]" ;;

      (ri) "${self}" rbi HEAD~"$1" ;;
      (rs) "${self}" rt --soft HEAD~"$1" && "${self}" cim "$(git log --format=%B --reverse [email protected]{1} | head -1)" ;;

La subkomandon rs mi uzas kiam ŝanĝojn mi volas kunpremegi neinterage. La argumento al ĝi estas cifero kio prezicigas kiom da ŝanĝo oni volas kunpremigi. Ekzemple, se la lastajn du ŝanĝojn mi volas kunpremegi, la jenan komandon mi uzas:

git rs 2

Aldonado

      (aum) "${self}" au; "${self}" cim "[email protected]" ;;
      (aux) "${self}" aum "x" ;;
      (a.m) "${self}" a.; "${self}" cim "[email protected]" ;;
      (a.x) "${self}" a.m "x" ;;

      (auxx) "${self}" aux; "${self}" rs 2 ;;
      (au.x) "${self}" a.x; "${self}" rs 2 ;;
      (auxx!) "${self}" auxx; "${self}" oo! ;;

La subkomando aum fariĝos mallongigo de au kaj cm orde. La subkomandon auxx mi uzas kiam ajn nur etajn ŝanĝojn mi faris sed novan videblan enskribon en la protokolo mi ne deziras havi.

Foraj deponejoj

      (re) "${git}" remote "[email protected]" ;;
      (rea) "${self}" re add "[email protected]" ;;
      (reao) "${self}" rea origin "[email protected]" ;;
      (reau) "${self}" rea upstream "[email protected]" ;;
      (rer) "${self}" re remove "[email protected]" ;;
      (ren) "${self}" re rename "[email protected]" ;;
      (rero) "${self}" rer origin "[email protected]" ;;
      (reru) "${self}" rer upstream "[email protected]" ;;
      (res) "${self}" re show "[email protected]" ;;
      (reso) "${self}" res origin ;;
      (resu) "${self}" res upstream ;;

Revizioj, filtrado, kaj kaŝujoj

      (rl) "${git}" rev-list "[email protected]" ;;
      (rla) "${self}" rl --all "[email protected]" ;;
      (rl0) "${self}" rl --max-parents=0 HEAD ;;

      (cp) "${git}" cherry-pick "[email protected]" ;;
      (cpc) "${self}" cp --continue "[email protected]" ;;
      (cpa) "${self}" cp --abort "[email protected]" ;;

      (fb) "${git}" filter-branch "[email protected]" ;;
      (fb!) "${self}" fb -f "[email protected]" ;;
      (fbm) "${self}" fb! --msg-filter "[email protected]" ;;
      (fbi) "${self}" fb! --index-filter "[email protected]" ;;
      (fbe) "${self}" fb! --env-filter "[email protected]" ;;

      (rp) "${git}" rev-parse "[email protected]" ;;
      (rph) "${self}" rp HEAD ;;

      (sh) "${git}" stash "[email protected]" ;;
      (shp) "${self}" sh pop "[email protected]" ;;

Kiam ajn tekstojn de ĉiuj antaŭaj ŝanĝmesaĝoj mi volas ŝanĝi, ekzemple la vorton hundo mi volas ŝanĝi al kato, la jenan komandon mi plenumas:

git fbm 'sed "s/hundo/kato/"'

Kiam ajn dosieron mi volas forigi tute el la deponejo, ekzemple dosiero.dat, la jenan komandon mi plenumas:

git fbi 'git rm --cached --ignore-unmatch dosiero.dat' HEAD

Kiam ajn la retpoŝadreson mi volas ŝanĝi, ekzemple, al [email protected], la jenan komandon mi plenumas:

git fbe 'export GIT_AUTHOR_EMAIL="[email protected]"; export GIT_COMMITTER_EMAIL="[email protected]"' --tag-name-filter cat -- --branches --tags

La jenan komandon mi tiam uzas sekve, por certigi ke la ŝanĝoj aperas en la fora deponejo:

git oo!

Subarboj, kaj submoduloj

      (st) "${git}" subtree "[email protected]" ;;
      (sta) "${self}" st add "[email protected]" ;;
      (stph) "${self}" st push "[email protected]" ;;
      (stpl) "${self}" st pull "[email protected]" ;;

      (sm) "${git}" submodule "[email protected]" ;;
      (sms) "${self}" sm status "[email protected]" ;;
      (smy) "${self}" sm summary "[email protected]" ;;
      (smu) "${self}" sm update "[email protected]" ;;
      (sma) "${self}" sm add "[email protected]" ;;
      (smi) "${self}" sm init "[email protected]" ;;

      (ref) "${git}" reflog "[email protected]" ;;

Ĉion rikolti

Jen da difinoj en unu loko:

function git () {
  local git= self= op=

  if [[ -n "${BASH}" ]]; then
    git=$(which git)
    self=${FUNCNAME}
  elif [[ -n "${ZSH_NAME}" ]]; then
    git=$(whence -p git)
    self=$0
  else
    echo "Meh"
    return 1
  fi

  if [[ $# -eq 0 ]]; then
    if [[ -n "${BASH}" ]]; then
      type "${self}" | less
    elif [[ -n "${ZSH_NAME}" ]]; then
      which "${self}" | less
    else
      echo "Meh"
      return 1
    fi
  else
    op="$1"
    shift

    case "${op}" in
      (i) touch .gitignore; "${git}" init; "${self}" a.; "${self}" cim "[email protected]" ;;
      (i!) "${self}" i "Pravaloriziĝu" ;;

      (s) "${git}" status ;;
      (c) "${git}" clone "[email protected]" ;;
      (h) "${git}" show "[email protected]" ;;
      (mv) "${git}" mv "[email protected]" ;;
      (mv!) "${git}" mv -f "[email protected]" ;;
      (me) "${git}" merge "[email protected]" ;;
      (ta) "${git}" tag "[email protected]" ;;
      (bl) "${git}" blame "[email protected]" ;;

      (cl) "${git}" clean "[email protected]" ;;
      (cl!) "${self}" cl -f ;;

      (ci) "${git}" commit "[email protected]" ;;
      (cia) "${self}" ci --amend "[email protected]" ;;
      (cim) "${self}" ci --message "[email protected]" ;;

      (co) "${git}" checkout "[email protected]" ;;
      (com) "${self}" co master ;;
      (cot) "${self}" co trunk ;;
      (co!) "${self}" co --force "[email protected]" ;;
      (cob) "${self}" co -b "[email protected]" ;;

      (ls) "${git}" ls-files "[email protected]" ;;
      (lsm) "${self}" ls -m ;;
      (lsd) "${self}" ls -d ;;
      (lsdrm) "${self}" lsd | xargs "${git}" rm ;;

      (rt) "${git}" reset "[email protected]" ;;
      (rt!) "${self}" rt --hard "[email protected]" ;;
      (rv) "${git}" revert "[email protected]" ;;

      (g) "${git}" grep "[email protected]" ;;
      (gi) "${self}" g -i "[email protected]" ;;

      (f) "${git}" fetch "[email protected]" ;;
      (fa) "${self}" f --all "[email protected]" ;;

      (rm) "${git}" rm "[email protected]" ;;
      (rmr) "${self}" rm -r "[email protected]" ;;
      (rm!) "${self}" rm -rf "[email protected]" ;;

      (rb) "${git}" rebase "[email protected]" ;;
      (rbi) "${self}" rb --interactive "[email protected]" ;;
      (rbc) "${self}" rb --continue "[email protected]" ;;
      (rbs) "${self}" rb --skip "[email protected]" ;;
      (rba) "${self}" rb --abort "[email protected]" ;;
      (rbs) "${self}" rb --skip "[email protected]" ;;
      (rbi!) "${self}" rbi --root "[email protected]" ;;

      (ri) "${self}" rbi HEAD~"$1" ;;
      (rs) "${self}" rt --soft HEAD~"$1" && "${self}" cim "$(git log --format=%B --reverse [email protected]{1} | head -1)" ;;

      (ph) "${git}" push "[email protected]" ;;
      (phu) "${self}" ph -u "[email protected]" ;;
      (ph!) "${self}" ph --force "[email protected]" ;;
      (pho) "${self}" phu origin "[email protected]" ;;
      (phom) "${self}" pho master "[email protected]" ;;

      (oo) "${self}" ph origin "$(git brh)" ;;
      (oo!) "${self}" ph! origin "$(git brh)" ;;

      (pl) "${git}" pull "[email protected]" ;;
      (pl!) "${self}" pl --force "[email protected]" ;;
      (plr) "${self}" pl --rebase "[email protected]" ;;
      (plro) "${self}" plr origin "[email protected]" ;;
      (plru) "${self}" plr upstream "[email protected]" ;;
      (plrom) "${self}" plro master ;;
      (plrum) "${self}" plru master ;;
      (plrot) "${self}" plro trunk ;;
      (plrut) "${self}" plru trunk ;;

      (a) "${git}" add "[email protected]" ;;
      (au) "${self}" a -u ;;
      (a.) "${self}" a . ;;

      (aum) "${self}" au; "${self}" cim "[email protected]" ;;
      (aux) "${self}" aum "x" ;;
      (a.m) "${self}" a.; "${self}" cim "[email protected]" ;;
      (a.x) "${self}" a.m "x" ;;

      (auxx) "${self}" aux; "${self}" rs 2 ;;
      (au.x) "${self}" a.x; "${self}" rs 2 ;;
      (auxx!) "${self}" auxx; "${self}" oo! ;;

      (l) "${git}" log "[email protected]" ;;
      (l1) "${self}" l -1 --pretty=%B ;;
      (lo) "${self}" l --oneline ;;
      (lp) "${self}" l --patch ;;
      (lp1) "${self}" lp -1 ;;
      (lpw) "${self}" lp --word-diff=color ;;

      (br) "${git}" branch "[email protected]" ;;
      (bra) "${self}" br -a ;;
      (brm) "${self}" br -m "[email protected]" ;;
      (brmh) "${self}" brm "$(git brh)" ;;
      (brd) "${self}" br -d "[email protected]" ;;
      (brD) "${self}" br -D "[email protected]" ;;
      (brh) "${git}" rev-parse --abbrev-ref HEAD ;;

      (d) "${git}" diff "[email protected]" ;;
      (dc) "${git}" diff --cached "[email protected]" ;;
      (dh) "${self}" d HEAD ;;
      (dhw) "${self}" d --word-diff=color ;;

      (re) "${git}" remote "[email protected]" ;;
      (rea) "${self}" re add "[email protected]" ;;
      (reao) "${self}" rea origin "[email protected]" ;;
      (reau) "${self}" rea upstream "[email protected]" ;;
      (rer) "${self}" re remove "[email protected]" ;;
      (ren) "${self}" re rename "[email protected]" ;;
      (rero) "${self}" rer origin "[email protected]" ;;
      (reru) "${self}" rer upstream "[email protected]" ;;
      (res) "${self}" re show "[email protected]" ;;
      (reso) "${self}" res origin ;;
      (resu) "${self}" res upstream ;;

      (rl) "${git}" rev-list "[email protected]" ;;
      (rla) "${self}" rl --all "[email protected]" ;;
      (rl0) "${self}" rl --max-parents=0 HEAD ;;

      (cp) "${git}" cherry-pick "[email protected]" ;;
      (cpc) "${self}" cp --continue "[email protected]" ;;
      (cpa) "${self}" cp --abort "[email protected]" ;;

      (fb) "${git}" filter-branch "[email protected]" ;;
      (fb!) "${self}" fb -f "[email protected]" ;;
      (fbm) "${self}" fb! --msg-filter "[email protected]" ;;
      (fbi) "${self}" fb! --index-filter "[email protected]" ;;
      (fbe) "${self}" fb! --env-filter "[email protected]" ;;

      (rp) "${git}" rev-parse "[email protected]" ;;
      (rph) "${self}" rp HEAD ;;

      (sh) "${git}" stash "[email protected]" ;;
      (shp) "${self}" sh pop "[email protected]" ;;

      (st) "${git}" subtree "[email protected]" ;;
      (sta) "${self}" st add "[email protected]" ;;
      (stph) "${self}" st push "[email protected]" ;;
      (stpl) "${self}" st pull "[email protected]" ;;

      (sm) "${git}" submodule "[email protected]" ;;
      (sms) "${self}" sm status "[email protected]" ;;
      (smy) "${self}" sm summary "[email protected]" ;;
      (smu) "${self}" sm update "[email protected]" ;;
      (sma) "${self}" sm add "[email protected]" ;;
      (smi) "${self}" sm init "[email protected]" ;;

      (ref) "${git}" reflog "[email protected]" ;;

      (*) "${git}" "${op}" "[email protected]" ;;
    esac
  fi
}

Mi devas mencii, ke se la funkcion supre ni jam havas en nia ŝela agordo kaj la jenan alinomon ni havas en ~/.gitconfig:

[alias]
  ls = "! echo hello world"

tiam la jenan komandon ni plenumos

git ls

aperos la listoj de dosieroj mastrumitaj de git, anstataŭ la teksto hello world sur la ekrano.

Finrimarkoj

Do, per tiu funkcio, mi povas labori per gito pli facile tial, ke mi nur devas pensi pli la mallongigoj. Krome aliron al miaj aliaj ŝelaj komandoj mi havas. Pro tio ke na tmux mi uzas, kiam ajn giton mi bezonas uzi, klavkombinon por la malfermado de alia tmux-fenestro sube mi nur devas premi. Tie, tiujn gitkomandojn mi povas facile sen la ŝanĝon de ekranvido kiun Magit bedaŭrinde faras. Min ĝi ebligas por pensi aparte inter la kodo kaj la mastrumado de la kodo mem.