Gabay

Mga branch sa Git: git branch, paggawa, paglipat, at pagbura

Na-update: · Skillaria.Top

Ang branch sa Git ay magaan na pointer papunta sa commit, at ipinapakita ng HEAD kung nasaang branch kayo ngayon. Ginagamit ang git branch para ilista, gumawa, magpalit ng pangalan, at magburá ng branch; ang git switch ang naglilipat sa pagitan nila, at ang git switch -c pangalan ay gumagawa at lumilipat nang sabay.

Ano ang branch sa Git

Ang branch sa Git ay hindi kopya ng project, kundi maliit na file na may hash ng isang commit. Mabilis gumawa ng branch, sa loob ng ilang fraction ng segundo, at halos walang espasyong nakokonsumo, dahil wala namang dinodoble ang Git: lahat ng branch ay tumuturo sa iisang object sa database ng repository. Kapag nag-commit kayo, ang pointer ng kasalukuyang branch ay gumagalaw lang papunta sa bagong commit.

Binabago nito ang pagtingin sa branches. Hindi sila dapat katakutan o tipirin: normal na practice ang hiwalay na branch para sa bawat task, pag-aayos, o eksperimento. Kapag hindi nagtagumpay ang eksperimento, buburahin ang branch, at malinis pa rin ang pangunahing history.

Makikita ninyo mismo na file ang branch:

$ cat .git/refs/heads/main
8b7d4e2a9f1c0d3e5b6a7c8d9e0f1a2b3c4d5e6f

(Sa malalaking repository, may ilang reference na nakapaloob sa .git/packed-refs, kaya maaaring walang ganitong file; hindi nagbabago ang diwa nito.)

HEAD sa Git: nasaan kayo ngayon

Ang HEAD ay pointer sa kung ano ang kasalukuyang "naka-checkout" sa working directory. Karaniwan, hindi sa commit tumuturo ang HEAD kundi sa branch:

$ cat .git/HEAD
ref: refs/heads/main

Ganito ang kadena: HEAD → main → commit. Ang bagong commit ay magkakaroon ng parent na commit kung saan nakaturo ang HEAD, tapos ilalipat ng Git ang branch na tinuturo ng HEAD. Kaya napupunta ang mga commit sa kasalukuyang branch.

Kapag lumipat kayo nang direkta sa commit o tag (git switch --detach v1.0 o git checkout 3f2a1c9), diretsong tumuturo ang HEAD sa commit. Ito ang tinatawag na detached HEAD. Ligtas tingnan ang code sa ganitong estado, pero hindi nakakabit sa anumang branch ang mga bagong commit, kaya madaling mawala pagkatapos ng paglipat. Kung nagsimula na kayong magbago, gumawa agad ng branch doon: git switch -c fix-from-old-version.

Sa mga expression, kapaki-pakinabang ang HEAD bilang panimulang punto: HEAD~1 ang naunang commit, HEAD~3 ang tatlong commit pabalik, at HEAD^2 ang pangalawang parent ng merge commit.

Paano tingnan ang mga branch: git branch

git branch            # lokal na branch, may * ang kasalukuyan
git branch -v         # kasama ang huling commit ng bawat isa
git branch -vv        # kasama ang upstream at pagkakaiba (behind/ahead)
git branch -r         # remote branch (origin/...)
git branch -a         # lahat ng branch
git branch --show-current   # pangalan lang ng kasalukuyang branch

Halimbawa ng output ng git branch -vv:

  feature/login 4c1e2d7 [origin/feature/login: ahead 2] Form ng login
* main          8b7d4e2 [origin/main] I-update ang README
  old-spike     1a9b3c0 Eksperimento sa cache

Makikita rito na may dalawang hindi pa naipapadalang commit ang feature/login, kapareho ng server ang main, at walang katapat sa server ang old-spike.

Makakatulong sa pag-filter ng branch ang git branch --merged (na-merge na sa kasalukuyan, kandidato para burahin), git branch --no-merged (hindi pa na-merge), at git branch --list 'feature/*' (ayon sa pattern).

Paano gumawa ng branch

May dalawang paraan. Ang git branch ay gumagawa ng branch pero nananatili kayo sa kasalukuyan:

git branch feature/login            # mula sa kasalukuyang commit
git branch hotfix v1.2.0            # mula sa tag
git branch review 3f2a1c9           # mula sa tiyak na commit

Mas madalas, gusto ninyong gumawa ng branch at agad lumipat dito. Para dito ang git switch -c (lumabas sa Git 2.23), o ang lumang katumbas nitong git checkout -b:

git switch -c feature/login
git switch -c hotfix origin/main    # bagong branch mula sa pinakabagong estado ng server

Magandang ugali: bago gumawa ng branch para sa task, i-update muna ang base: git fetch, tapos git switch -c feature/x origin/main. Sa ganitong paraan, magsisimula ang branch sa up-to-date na code, hindi sa matagal nang hindi na-update na lokal na main.

Paano pangalanan ang mga branch

Karaniwang kasunduan sa mga team: prefix ayon sa uri ng trabaho, at maikling paglalarawan na may gitling: feature/user-avatar, fix/login-timeout, chore/update-deps, minsan may numero ng task: feature/SHOP-142-cart. Hindi puwede ang space, ~ ^ : ? * [, dalawang tuldok na magkasunod, at pagtatapos sa .lock.

Paano lumipat ng branch: git switch

git switch main             # lumipat sa umiiral na branch
git switch -                # bumalik sa naunang branch
git switch feature/login    # kung walang lokal pero may origin/feature/login,
                            # gagawa ang Git ng lokal at ilalakip ito sa remote

Kapag lumilipat, pinapalitan ng Git ang mga file sa working directory ng bersyon mula sa target na branch. Dadalhin ninyo ang mga hindi pa naka-commit na pagbabago kung hindi sila nagsasalungatan sa target na branch. Kung nagsasalungatan, tatanggi ang Git:

error: Your local changes to the following files would be overwritten by checkout:
        app.js
Please commit your changes or stash them before you switch branches.

Mga solusyon: mag-commit, itabi gamit ang git stash (ibalik mamaya gamit ang git stash pop), o sadyang dalhin ang mga pagbabago na may pagsubok ng merge: git switch -m main. Itatapon ng flag na --discard-changes ang mga edit; gamitin lang ito kung sigurado kayong hindi na kailangan ang mga iyon.

Bakit git switch at hindi checkout? Kayang magpalit ng branch ng checkout, pero kaya rin nitong i-overwrite ang mga file, kaya madaling magkamali. Ang switch ay gumagawa lang ng isang bagay: nagtatrabaho sa mga branch, kaya mas ligtas. Detalyadong paghahambing ng checkout, switch, at restore ay nasa hiwalay na artikulo.

Paano magpalit ng pangalan ng branch

git branch -m new-name              # palitan ang pangalan ng kasalukuyan
git branch -m old-name new-name     # palitan ang pangalan ng alinmang branch
git branch -M main                  # kapareho, pero i-o-overwrite ang umiiral na branch

Kung nasa server na ang branch, lokal lang ang pagpapalit ng pangalan. I-push ang bago at burahin ang luma:

git push -u origin new-name
git push origin --delete old-name

Paano magburá ng branch

git branch -d feature/login     # buburahin lang kung na-merge na
git branch -D old-spike         # pilit na burahin
git push origin --delete feature/login   # burahin sa server

Pinoprotektahan ng -d ang trabaho: kapag may commit sa branch na wala sa kasalukuyang branch (o sa upstream nito), tatanggi ang Git na may mensaheng "The branch 'x' is not fully merged". Binubura ng -D nang walang tanong. Hindi maaaring burahin ang kasalukuyang branch; lumipat muna sa iba.

Nabura ba ninyo ang hindi dapat? Hindi agad nawawala ang mga commit. Hanapin ang hash ng huling commit ng branch sa git reflog at ibalik ito: git branch old-spike 1a9b3c0.

Ang mga lumang bookmark ng remote branch na wala na sa server ay nililinis ng git fetch --prune.

Pagkakabit ng lokal na branch sa remote branch

Maaaring may upstream ang lokal na branch: ang remote branch na pinaghahambingan at sini-sync nito. Kailangan ito para gumana ang git push at git pull nang walang argumento, at para ipakita ng git status ang "ahead/behind".

git push -u origin feature/login                 # sa unang pag-push
git branch --set-upstream-to=origin/main main    # para sa umiiral na branch
git branch --unset-upstream                      # alisin ang koneksyon

Pagsasama ng branch: sa maikling salita

Gumagawa ng branch para pagsamahin ito pagkatapos. Kapag tapos na ang trabaho, lumipat sa target na branch at i-merge dito ang sa inyo:

git switch main
git merge feature/login

Kung hindi pa nakakalayo ang main mula nang gawin ang branch, gagawa ang Git ng fast-forward: ililipat lang nito ang pointer ng main sa huling commit ng branch, nang walang merge commit. Kung parehong may bagong commit ang dalawang branch, magkakaroon ng three-way merge: hahanapin ng Git ang karaniwang ninuno, ikukumpara ang dalawang panig, at gagawa ng merge commit na may dalawang parent. Sa mga team, kadalasang ginagawa ang merge sa server gamit ang pull request, at lokal lang kinukuha ang bagong main.

Buod na cheat sheet ng branch

GawainCommand
Listahan ng branchgit branch -vv
Gumawa ng branchgit branch pangalan
Gumawa at lumipatgit switch -c pangalan
Lumipatgit switch pangalan
Bumalik sa naunanggit switch -
Palitan ang pangalangit branch -m luma bago
Burahin ang na-merge nagit branch -d pangalan
Pilit na burahingit branch -D pangalan
Burahin sa servergit push origin --delete pangalan
Mga branch na puwedeng burahingit branch --merged
Ibalik ang naburagit reflog, tapos git branch pangalan hash

Karaniwang pagkakamali ng baguhan

  • Nagtatrabaho nang diretso sa main. Kung may commit na nagawa pero hindi pa naipapadala, gumawa ng branch sa kasalukuyang kinalalagyan (git branch feature/x), tapos ibalik ang main sa server: git reset --hard origin/main (siguraduhing naka-commit na ang lahat).
  • Branch mula sa lumang main. Unahin ang git fetch, at gumawa ng branch mula sa origin/main.
  • Mga commit sa detached HEAD. Bago lumipat, gumawa ng branch; kung nakalipat na, hanapin ang mga commit sa git reflog.
  • Matagal nang branch. Mas masakit ang merge kapag mas matagal nabubuhay nang hiwalay ang branch. Regular na kunin ang main at i-merge ang trabaho sa maliliit na bahagi.

Mga branch sa team work

Iba-iba ang proseso ng mga team, pero halos laging isa sa dalawang scheme ang ginagamit. Sa GitHub Flow, may iisang pangmatagalang branch na main na laging handang i-deploy, at maiikling feature branch na nagme-merge sa pamamagitan ng pull request pagkatapos ng review at CI checks. Sa Git Flow, may dagdag na develop, release branch, at hotfix branch; mas mabigat ito at angkop sa produktong may bihira at versioned na release.

Anuman ang scheme, pareho ang mga pangkalahatang tuntunin: isang branch para sa isang task, nabubuhay ang branch nang ilang araw at hindi buwan, bago ang pull request ay na-update ang branch sa pinakabagong main, at pagkatapos ng merge ay binubura ang branch sa lokal at sa server. Ang pangunahing branch ay pinoprotektahan sa settings ng repository: bawal ang direktang push at force push dito, at ang merge ay dumadaan lang sa review.

Paano tingnan ang history ng mga branch

Pinakamadaling maintindihan ang relasyon ng mga branch sa pamamagitan ng graph: iginuguhit ng git log --oneline --graph --all ang lahat ng branch at ang punto ng paghihiwalay nila sa terminal. Para makita ang mga commit na nasa branch pero wala pa sa main, gamitin ang git log main..feature/login, at para sa pagkakaiba ng mga file, ang git diff main...feature/login (tatlong tuldok ay ikinukumpara sa karaniwang ninuno, kaya ipinapakita lang nito ang pagbabago ng mismong branch).

Buod

Ang branch sa Git ay murang pointer papunta sa commit, at ang HEAD ay pointer papunta sa kasalukuyang branch. Pinamamahalaan ng git branch ang mga branch (listahan, paggawa, pagpapalit ng pangalan, pagburá), inililipat ng git switch sa pagitan nila, at ginagawa ng git switch -c ang dalawang aksiyon nang sabay. Ang mga branch, HEAD, fast-forward, at three-way merge ay itinuturo gamit ang totoong halimbawa sa kursong Git namin.

Mga madalas itanong

Ilang branch ang puwedeng gawin sa Git?

Halos walang limitasyon: bawat branch ay reference na ilang dosenang byte lang ang laki, kaya walang problema sa espasyo.

Nabubura ba ang mga commit kasabay ng branch?

Hindi agad. Ang mga commit na wala nang tumuturo ay nananatili pa nang ilang panahon at makikita sa git reflog, hanggang sa lihim na burahin ng garbage collector (karaniwan, hindi bago ang 30 araw para sa mga hindi maabot na reflog entry).

Paano malalaman kung saang branch galing ang kasalukuyang branch?

Hindi ito itinatago ng Git: naaalala lang ng branch ang sarili nitong commit. Makikita ang karaniwang ninuno sa main gamit ang git merge-base HEAD main.

Ano ang pagkakaiba ng branch at tag?

Gumagalaw pasulong ang branch sa bawat bagong commit, habang ang tag ay nakapirmi sa iisang commit at ginagamit para markahan ang release.

Bakit main at hindi master?

Pangalan lang ng default na branch iyon. Lumipat na ang maraming serbisyo sa main; puwedeng itakda ang pangalan para sa mga bagong repository gamit ang git config --global init.defaultBranch main.

Pag-aralan ito sa video

Detalyadong tinatalakay ang paksang ito, may praktis, sa kursong “Git с нуля до уверенного разработчика”.

Pumunta sa kurso