6 पॉइंट द्वारा GN⁺ 2023-11-03 | 1 टिप्पणियां | WhatsApp पर शेयर करें
  • Git को लंबे समय तक इस्तेमाल करने के बाद भी इसमें शब्दों की पुनरावृत्ति और दोबारा उपयोग बहुत है, इसलिए सिर्फ commands याद कर लेने से असल behavior का अनुमान लगाना मुश्किल होता है
  • HEAD, heads, detached HEAD, ours/theirs, ../... जैसे एक ही शब्द और symbols context के हिसाब से अलग अर्थ ले लेते हैं
  • index, staged, cached सभी .git/index से जुड़े हैं, लेकिन reset, revert, restore मिलते-जुलते नामों के बावजूद commit history, working tree और branch pointer पर अलग-अलग असर डालते हैं
  • main का remote को track करना और origin/main जैसी remote-tracking branch अलग चीजें हैं, और checkout एक ही command में branch switch और file restore दोनों को समेटे हुए है
  • Git को समझने के लिए अलग-अलग commands से ज्यादा branch, reference, commit, index और remote tracking state के साथ काम करने वाले internal model को देखना जरूरी है

HEAD, branch और detached HEAD

  • Git में heads branches को दर्शाते हैं, और internally branches .git/refs/heads directory में stored होती हैं
    • आधिकारिक Git glossary branch को उसके ऊपर मौजूद सभी commits और head को सबसे recent commit के रूप में अलग करती है, लेकिन इन्हें उसी target को देखने के दो तरीकों के रूप में समझा जा सकता है
  • HEAD current branch को point करता है और .git/HEAD में stored होता है
    • head branch है, और HEAD current branch है” जैसा वाक्य ही Git terminology के confusion को अच्छी तरह दिखाता है
  • detached HEAD state वह स्थिति है जिसमें HEAD किसी branch के बजाय सीधे commit ID को point करता है
    • tag को checkout करने पर, क्योंकि tag branch नहीं होता, detached HEAD state हो सकती है
    • इस state में git pull काम नहीं करता, और git push भी किसी खास तरीके के बिना काम नहीं करता
    • git commit, git merge, git rebase, git cherry-pick संभव हैं, लेकिन नए commits किसी branch से जुड़े नहीं रहते, इसलिए उन्हें ढूंढना मुश्किल हो सकता है
    • नई branch बनाकर या existing branch पर switch करके detached HEAD state से बाहर निकला जा सकता है

merge और rebase में बदलते ours और theirs

  • conflict resolution में git checkout --ours file.txt “ours” वाली file चुनता है, लेकिन merge और rebase के reference point अलग होते हैं
  • merge में current branch ours होती है, और merge होकर आने वाली branch theirs होती है
    • उदाहरण: git checkout merge-into-ours के बाद git merge from-theirs चलाने पर current branch ours बनती है
  • rebase में current branch theirs होती है, और rebase target branch ours होती है
    • उदाहरण: git checkout theirs के बाद git rebase ours चलाने पर target branch ours बनती है
  • यह फर्क इस बात से जुड़ा है कि git rebase main internally current branch के commits को main branch की copy में बार-बार merge करने के तरीके से काम करता है
  • ourstheirs ours और theirs शब्दों को संक्षेप में समझाता है
    • VSCode के “current change” और “incoming change” भी इसी तरह confuse कर सकते हैं

remote status messages और fast-forward

  • Your branch is up to date with 'origin/main' का मतलब यह नहीं कि current main remote की latest state में है
    • इसका मतलब है कि last git fetch या git pull के समय के origin/main और local branch समान हैं
    • अगर last fetch 5 दिन पहले हुआ था, तो यह “5 दिन पहले के हिसाब से” up to date है
  • Git reflog में recent fetch time की जानकारी store करता है, लेकिन status message में “last fetch के आधार पर” समय नहीं दिखाया जाता
  • can be fast-forwarded का मतलब है कि remote branch local branch से आगे है, और local में अलग commits नहीं हैं, इसलिए सिर्फ pointer को आगे ले जाया जा सकता है
    • उदाहरण: अगर main A-B-C है और origin/main A-B-C-D-E है, तो git pull के बाद दोनों A-B-C-D-E हो जाएंगे
    • इस case में merge conflict की संभावना नहीं होती
  • fast-forward संभव न होने का मतलब है कि दोनों branches अलग-अलग दिशाओं में बढ़ चुकी हैं
    • उदाहरण: अगर main में X commit है जो origin/main में नहीं है, और origin/main में D, E हैं जो main में नहीं हैं, तो fast-forward संभव नहीं है
    • तब Git दिखाता है कि दोनों branches diverged state में हैं और दोनों के पास अलग-अलग commit counts हैं

commit चयन syntax: ^, ~, .., ...

  • HEAD^ और HEAD~ दोनों 1 commit पहले को point करते हैं
    • HEAD^^^, HEAD~~~, HEAD~3 सभी 3 commits पहले को point करते हैं
  • merge commit जैसे कई parents वाले commit में HEAD^2, HEAD^3 का अर्थ अलग हो जाता है
    • HEAD^ पहला parent है
    • HEAD^2 दूसरा parent है
    • HEAD^3 तीसरा parent है
    • HEAD~3 parent के parent के parent को दर्शाता है, इसलिए यह HEAD^3 से अलग है
  • git log main..test और git log main...test भी अलग तरह से काम करते हैं
    • main..test केवल test में मौजूद commits दिखाता है
    • test..main केवल main में मौजूद commits दिखाता है
    • main...test दोनों तरफ ही मौजूद commits को साथ दिखाता है
  • git diff में .. और ... को git log से अलग तरह से interpret किया जाता है
    • git diff test..main test side के changes और main side के changes दोनों को शामिल करके compare करता है
    • git diff test...main common ancestor और main side के end को compare करके एक तरफ का diff ही दिखाता है
  • dots notation की उलझन pain in dots में भी और discuss की गई है

reference, refspec, tree-ish

  • Git में reference कई अर्थों में इस्तेमाल होता है
    • main, v0.2 जैसी branches और tags
    • current branch को point करने वाला HEAD
    • HEAD^^^ जैसी expressions जिन्हें commit ID के रूप में interpret किया जाता है
  • Git documentation HEAD^^^ जैसी expressions को सख्ती से “revision parameters” कहती है, लेकिन रोजमर्रा में इन्हें reference की तरह handle किया जा सकता है
  • symbolic reference का मतलब ऐसा reference है जो किसी दूसरे reference को point करता है, जैसे HEAD
    • HEAD Git के core commands के behavior पर बड़ा असर डालने वाला central concept है
  • .git/config की remote settings में refspec होता है
    • उदाहरण: +refs/heads/main:refs/remotes/origin/main
    • default git clone या git remote add जो values बनाते हैं, अक्सर उन्हें ही इस्तेमाल किया जाता है
  • tree-ish उन targets को दर्शाता है जो git checkout THING . में THING हो सकते हैं
    • commit ID
    • main, HEAD^^, v0.3.2 जैसे commit references
    • main:./docs जैसी commit के अंदर की subdirectory
    • practical तौर पर कई बार इसे “commit या commit reference” समझना काफी होता है

index, staged, cached

  • index, staged, cached सभी .git/index से जुड़े हैं
    • .git/index वह file है जो git add से changes को stage करते समय इस्तेमाल होती है
  • एक ही target को दर्शाने वाले शब्द कई commands में बिखरे हुए हैं
    • git diff --cached
    • git rm --cached
    • git diff --staged
    • .git/index
  • हालांकि --index और --cached flags का मतलब हमेशा एक जैसा नहीं होता
    • Git lead maintainer Junio Hamano का लेख detailed differences समझाता है
  • performance कारणों से index untracked files को भी list करता है, लेकिन आम तौर पर staging area को untracked files शामिल करने वाला नहीं माना जाता

reset, revert, restore

  • reset, revert, restore मिलते-जुलते शब्द हैं, लेकिन Git में इनके असर के targets अलग हैं
  • git revert COMMIT current branch में COMMIT के उलटे operation वाला नया commit बनाता है
    • अगर COMMIT ने 3 lines जोड़ी थीं, तो नया commit वे 3 lines हटाता है
  • git reset --hard COMMIT current branch को जबरन COMMIT के समय की state में वापस ले जाता है
    • यह COMMIT के बाद के नए changes मिटाने वाला बहुत risky operation है
  • git restore --source=COMMIT PATH PATH की files को COMMIT के समय वाली state में लौटाता है
    • यह दूसरी files या commit history को नहीं बदलता
  • git reset --hard और git restore . अकेले इस्तेमाल करने पर आम तौर पर मिलते-जुलते काम करते हैं, लेकिन git reset --hard COMMIT और git restore --source COMMIT . पूरी तरह अलग तरह से काम करते हैं

track, remote-tracking branch, untracked files

  • Git track शब्द को तीन तरीकों से इस्तेमाल करता है
    • git status का Untracked files: उन files को दर्शाता है जिन्हें Git manage नहीं करता और जो commit में शामिल नहीं हैं
    • origin/main जैसी remote-tracking branch एक local reference है जिसमें last git pull या git fetch के समय remote origin के main द्वारा point की गई commit ID होती है
    • “branch foo set up to track remote branch bar from origin” की तरह local branch को remote branch track करने के लिए configure किया जा सकता है
  • यह कहना कि main remote को track करने वाली branch है और यह कहना कि origin/main remote-tracking branch है, दोनों अलग बातें हैं
  • main असली branch है, इसलिए इस पर commits बनाए और merge किए जा सकते हैं
    • .git/config में remote main को track करने के लिए configure होने पर git pull और git push आसानी से इस्तेमाल किए जा सकते हैं
  • origin/main “remote-tracking branch” नाम होने के बावजूद normal branch नहीं है
    • इस पर सीधे commit नहीं किया जा सकता
    • यह केवल git pull या git fetch से remote की latest main state लाते समय update होती है

checkout, reflog, merge/rebase/cherry-pick

  • git checkout एक ही command में दो अलग काम रखता है
    • git checkout BRANCH branch switch करता है
    • git checkout file.txt file.txt के unstaged changes discard करता है
  • इस confusion को कम करने के लिए Git ने functionality को git switch और git restore में बांटा, लेकिन पुराना checkout अभी भी इस्तेमाल किया जा सकता है
  • reflog reference log है, यानी reference ने past में किसे point किया था इसका record
    • reference एक broad term है जिसमें branch, tag और HEAD शामिल हैं
    • reflog बहुत खराब Git situations से निकलने में मदद कर सकता है, जैसे गलती से important branch delete हो जाना
  • merge, rebase, cherry-pick commits को combine करने के अलग-अलग तरीके हैं
    • merge दो branches को जोड़ने वाला एक नया commit बनाता है
    • rebase current branch के commits को target branch के ऊपर एक-एक करके copy करता है
    • cherry-pick rebase जैसा है, लेकिन syntax अलग है और यह commits को current branch में copy करता है
  • git rebase --onto main otherbranch mybranch का इस्तेमाल mybranch के कुछ commits ही main के ऊपर ले जाने के लिए किया जा सकता है
    • example structure में जब केवल F, G को main पर rebase करना हो, तो इसका इस्तेमाल किया जा सकता है
    • इसमें तीन branch names आते हैं, इसलिए syntax याद रखना मुश्किल है

commit और बाकी भ्रमित करने वाले शब्द

  • commit Git में verb और noun दोनों के रूप में इस्तेमाल होता है
    • verb: “बार-बार commit करो”
    • noun: main का सबसे recent commit
  • Git commit को तीन तरीकों से देखा जा सकता है
    • सभी files की current state का snapshot
    • parent commit के साथ diff
    • पिछले सभी commits की history
  • अलग-अलग commands commit को अलग तरह से handle करती हैं
    • git show commit को diff की तरह handle करता है
    • git log commit को history की तरह handle करता है
    • git restore commit को snapshot की तरह handle करता है
  • blob, tree, origin, upstream, downstream, fetch और pull का संबंध, stash, worktree, subtree, submodule भी भ्रमित करने वाली Git terminology में शामिल हैं
  • GitHub terminology में “pull request”, “squash and merge”, “rebase and merge” भ्रमित करने वाले examples माने जाते हैं

बार-बार लौटने वाले confusion के तीन axes

  • खास तौर पर confusing Git terminology को तीन बातों में समेटा जा सकता है
    • head branch है, और HEAD current branch है
    • “remote tracking branch” और “branch that tracks a remote” अलग चीजें हैं
    • index, staged, cached सभी एक ही target को point करते हैं
  • 2012 का the most confusing git terminology भी बताता है कि Git terminology CVS और Subversion terminology से कैसे जुड़ती है
  • Git terminology का confusion कुछ special features तक सीमित नहीं है, बल्कि core functionality में बार-बार दिखता है
  • खासकर branches पर चर्चा करते समय “tracking” कई तरीकों से इस्तेमाल होता है, इसलिए पहली बार देखने पर फर्क पहचानना मुश्किल होता है
  • कुछ explanations में Git के rare corners शामिल हैं, इसलिए गलती होने की संभावना का caveat बचा हुआ है

1 टिप्पणियां

 
GN⁺ 2023-11-03
Hacker News की राय
  • इनमें से ज़्यादातर शब्द याद रखना मेरे लिए मुश्किल था, लेकिन जिस मुख्य बात ने सब कुछ फिट कर दिया, वह यह थी कि Git में बहुत-सी चीज़ें अंत में commit की ओर इशारा करने वाले pointer ही हैं
    branch नाम, HEAD, tag—ये सब pointer हैं। HEAD उस commit की ओर इशारा करता है जिसे आप अभी देख रहे हैं, और my-feature जैसा branch नाम उस branch के सबसे नए commit की ओर इशारा करता है। अगर main पर रहते हुए git checkout -b my-feature करें, तो main, my-feature, और HEAD सभी main के सबसे नए commit की ओर इशारा करेंगे
    my-branch पर हर बार commit करने पर HEAD और my-branch नए commit की ओर इशारा करने के लिए आगे बढ़ते हैं। detached HEAD का मतलब है कि HEAD जिस commit की ओर इशारा कर रहा है, उस commit की ओर कोई branch इशारा नहीं कर रही। tag और branch में फर्क यह है कि tag किसी खास commit की ओर इशारा करता है और हिलता नहीं
    एक और चीज़ जो उलझाती थी, वह यह थी कि कई commands असंगत लगती हैं क्योंकि Git default arguments मानकर चलता है। git checkout file.txt वही है जो git checkout HEAD -- file.txt, और जब आप my-branch पर हों तो git rebase main वही है जो git rebase main my-branch। हालांकि बाद वाला रूप किसी दूसरी branch से भी चलाया जा सकता है
    आखिर में, जब सब गड़बड़ा जाए, तो किसी भी अजीब हालत से बाहर निकलने में मदद करने वाली command git reflog है। यह वे सभी commits दिखाती है जिनकी ओर HEAD ने इशारा किया था। फिर भी अच्छा है कि Git इस उलझन को मान रहा है और कम चौंकाने वाले, ज्यादा सरल interface वाली commands बना रहा है
    • Git की इसी अवधारणा के लिए उसका दिया हुआ नाम इस्तेमाल करें, तो “commit pointer” refs हैं। इसलिए नाम reflog पड़ा
      एक और बात जो Git इस्तेमाल करने वाले कई लोग अक्सर याद नहीं रखते: fetch किए गए remote के branch या tag refs भी सभी refs ही होते हैं, इसलिए जहाँ भी ref नाम इस्तेमाल किया जा सकता है, वहाँ इन्हें reference किया जा सकता है
      उदाहरण के लिए, अगर आप कहना चाहें, “इस branch में जो भी हो फर्क नहीं पड़ता; fast-forward नहीं, merge नहीं, rebase नहीं; बस local branch को remote की सामग्री से overwrite कर दो,” तो ऐसे करें: git checkout foo, git reset --hard origin/foo
    • सटीक तौर पर, HEAD pointer सीधे commit की ओर इशारा नहीं करता; आम तौर पर वह my-branch जैसे branch pointer की ओर इशारा करता है, और वह branch pointer commit की ओर इशारा करता है। detached HEAD स्थिति इसका अपवाद है
      my-branch पर commit करते समय HEAD और my-branch दोनों नए commit पर नहीं जाते; HEAD लगातार my-branch pointer की ओर इशारा करता रहता है और सिर्फ my-branch नए commit की ओर इशारा करने के लिए आगे बढ़ता है। बेशक, अगर HEAD का पीछा करते हुए my-branch से होकर commit तक जाएँ, तो आप नए commit तक पहुँचेंगे
      detached HEAD वह स्थिति है जिसमें HEAD, branch pointer के बजाय सीधे commit की ओर इशारा करता है। detached HEAD स्थिति में भी HEAD और branch pointer दोनों सबसे नए commit की ओर इशारा कर सकते हैं। git log --decorate देखने पर सामान्य (HEAD -> my-branch) के बजाय सबसे नए commit पर (HEAD, my-branch) जैसा दिखता है
    • यह व्याख्या अच्छी है। हालांकि कभी-कभी जो और ज्यादा उलझन पैदा करता है, वह यह है कि tag दो तरह के होते हैं। ज़्यादातर tags, जैसा कहा गया, commit object की ओर इशारा करने वाले lightweight tags होते हैं, उससे ज्यादा कुछ नहीं
      दूसरी ओर annotated tags message, timestamp, SHA आदि रख सकते हैं। ये proper Git objects होते हैं और commit objects की तरह काफी व्यवहार करते हैं, लेकिन आम तौर पर फिर भी किसी दूसरे Git object, अक्सर commit, को reference करते हैं
    • अगर आप मेरी तरह जरूरत से ज्यादा सावधान हैं, तो conflict-heavy मुश्किल प्रक्रिया या कई moves शुरू करने से पहले git rev-parse HEAD चलाकर उस string को किसी सुरक्षित जगह copy कर लेना भी अच्छा है
      इससे यह भरोसा रहता है कि आपने आखिरी सही मानी गई स्थिति को ठीक-ठीक mark कर लिया है। आम तौर पर chaos में कुछ कदम अंदर के किसी point पर नहीं, बल्कि आखिरी सही स्थिति पर वापस जाया जा सकता है। बेशक, यह मानकर कि आपने git gc या git filter-branch जैसी चीज़ें लापरवाही से नहीं चलाईं
    • यह व्याख्या यह भी अच्छी तरह दिखाती है कि Git के अंदर की tree structure ही सब कुछ चलाती है
      मज़ाक जैसा लगता है, लेकिन पूरी तरह मज़ाक नहीं: Git इस्तेमाल करने के लिए सचमुच computer science degree चाहिए, यह कहना गलत नहीं है। मैं सहमत हूँ कि Git के default arguments बहुत inconsistent user experience बनाते हैं
      git checkout ., git reset --hard/soft, git cleanup—ये सब बेहद मिलते-जुलते दिखते हैं, लेकिन असल में बहुत अलग हैं। फिर भी Perforce या SVN की तुलना में मुझे अब भी Git पसंद है। पहले मुझे Mercurial थोड़ा ज़्यादा पसंद था, लेकिन पता नहीं आज भी ऐसा होगा या नहीं
      git reflog राजा है और सच दिखाता है
  • Git को एक और बेबुनियाद tech fad की वजह से version control युद्ध में “जीते” हुए करीब 10 साल हो गए हैं, लेकिन अब भी उन कामों में दिक्कत होती है जो मामूली होने चाहिए
    मुझे याद है मैंने Linus Torvalds का लिखा कुछ पढ़ा था कि उन्हें यह देखकर हैरानी हुई कि लोग उसके ऊपर कोई ज्यादा friendly layer डाले बिना सीधे Git इस्तेमाल करने लगे। अगर industry आत्म-मंथन कर पाती, तो वह मानती कि Git चुनना गलती थी और किसी दूसरे version control system पर चली जाती। ऐसे tool पर इतना समय बर्बाद न करें जिसका काम बस text store करना है
    • मैं Git को text storage tool के रूप में नहीं देखता। यह कई लोगों द्वारा उसी “text” में किए जाने वाले बदलावों को काफी सटीक और भरोसेमंद ढंग से coordinate करता है, वह भी किसी की progress रोके बिना। Word में एक बार करके देखें, फर्क बड़ा है
      बेशक यह बेहतर हो सकता है। फिर भी Git को मिलने वाली नफरत हमेशा हैरान करती है। Git शानदार tool है, और non-developers के लिए बनाए गए Word या Google Docs जैसे tools से बहुत आगे है
      शायद इसलिए कि मैं इतना उम्रदराज़ हूँ कि Subversion के king होने का दौर याद है
    • पूरी तरह सहमत
      हर हफ्ते मैं colleagues को Git की वजह से उलझते देखता हूँ, online मदद माँगते posts देखता हूँ, और यहाँ की तरह ऐसे posts भी देखता हूँ जो उन चीज़ों को फिर समझाने की कोशिश करते हैं जिन्हें simple होना चाहिए
      coding के दौरान SVN, TFVC, Perforce आदि में अपनी बनाई गड़बड़ी को undo करने में लोगों को घंटों बर्बाद करते हुए मुझे याद नहीं
      tools ज़िंदगी आसान बनाने के लिए होते हैं। अगर वे ऐसा नहीं कर पाते, तो उन पर समय लगाना worth नहीं है
    • 2013 तक भी यह बिल्कुल साफ नहीं था कि Git जीतेगा। darcs, Mercurial, svn, यहाँ तक कि cvs users भी काफी थे, और उस दौर के tools में आम तौर पर इन सभी को support करने वाले plugins होते थे

काश अभी भी ऐसी विविधता होती। Git monoculture का मतलब यह भी है कि जो भी Git को replace करना चाहता है, उसे पहले Git को फिर से implement करना पड़ेगा। इसलिए हम ASCII या Scroll Lock key की तरह Git से लगभग हमेशा के लिए बंध जाते हैं

  • Git अच्छे कारणों से जीता था, और पिछली चीज़ों से साफ़ तौर पर बेहतर था। आज jQuery की तरह Git को कोसना trend हो सकता है, लेकिन जब यह आया था, तब यह स्पष्ट सुधार था
  • इसी तरह की समस्या पर, कि हम Git में क्यों फँस सकते हैं, मैंने हाल ही में एक लेख लिखा था
    मुख्य चिंता यह है कि GitHub इतना अच्छा है कि जब तक GitHub Git को text management engine से अलग नहीं करता और दूसरे engines की अनुमति नहीं देता, हम Git से बंधे रहेंगे
    https://trolololo.xyz/github
    https://news.ycombinator.com/item?id=38098109
  • Git terminology एक clinical case जैसी है, जहाँ कई शब्द पहले से उसके काम करने का तरीका समझ लेने के बाद तो समझ आते हैं, लेकिन implementation details न पता हों या उन्हें दूसरे शब्दों के साथ रखा जाए तो वे लगभग कोई अर्थ नहीं रखते
    ये leaky abstraction जैसे शब्द हैं
    • आंशिक रूप से सही है, लेकिन यह इसलिए भी है कि Git के अलग-अलग हिस्से अलग-अलग लोगों ने बनाए और उनके नाम अलग-अलग रखे। Linus ने मूल रूप से इसे cache कहा था, और वह सबसे computer-science वाला शब्द था
      बाद में लगता है Junio ने इसे distributed version control system के लिए ज़्यादा specific index में बदल दिया, और अधिकतर users इसे staging area कहते थे। अब इस शब्द का विकास Git UI और internals में fossil की तरह बचा हुआ है
    • ऐसा नहीं कि यह समझ में आता है; यह बस ढीली-ढाली naming है। अच्छे नाम रखने में मेहनत लगती है, और Git के शुरुआती developers ने वह नहीं की
    • सोचिए अगर basic use के लिए operating system, IDE, compiler internals जानना ज़रूरी हो, तो यह असल में खराब API design है
  • “Your branch is up to date with origin/master” वह सबसे बड़ा झूठ है जो मैं रोज़ सुनता हूँ। इसलिए हर बार बस pull कर देता हूँ
    • कड़ाई से देखें तो यह सच है। origin/master का मतलब origin पर मौजूद master नहीं है, बल्कि वह commit है जिस पर आख़िरी बार ज्ञात origin/master point कर रहा था। यह value fetch करने पर update होती है, और pull अपने-आप fetch करता है
      ls -l .git/refs/remotes/origin/master देखने पर पता चलेगा कि origin/master मेरे system में बस एक file है। यह कब बदली, वह भी देखा जा सकता है। यह जादू की तरह update नहीं होती
      जब आप git fetch origin करते हैं और बदलाव होते हैं, तो timestamp और contents बदल जाते हैं। cat .git/refs/remotes/origin/master से इसे देख सकते हैं
      Git की बुनियाद बहुत सरल है, इतनी कि core data structures और कुछ operations एक दिन में implement किए जा सकते हैं। यह जानना सचमुच क़ीमती है। पता नहीं कैसे Git ने काफ़ी सरल core के ऊपर बेहद जटिल user interface बना दिया
    • उस message का मतलब बस यह है कि जब तक Git को साफ़ निर्देश न दिया जाए, वह internet या remote repository से connect करके updates check नहीं करता। मुझे यह गुण अपने-आप में अच्छा लगता है। बस message और स्पष्ट हो सकता था
    • “Your branch is up to date with the local copy of origin/master, last updated on XXXX-XX-XX:XX:XX:XX” जैसा होना चाहिए था
    • मैं local master branch हटा देता हूँ। आम तौर पर master पर push नहीं कर सकता, या वैसे भी master पर सीधे काम नहीं करना चाहता। तो local में बदलाव-योग्य master branch रखने की कोई वजह नहीं है
      इसलिए केवल origin/master update करना होता है, और उसके लिए fetch काफ़ी है
    • git fetch && git pull
      3 साल बाद retire होकर इस टूटे-फूटे कचरे से हाथ धो लेने के दिन का इंतज़ार कर रहा हूँ
  • Git आने के लगभग शुरुआती दिनों से इसे इस्तेमाल कर रहा हूँ, लेकिन porcelain के बारे में इसी हफ्ते पता चला। मेरे पास एक project है जो git status output parse करता है, और --porcelain flag लगाने से सच में मदद मिली। यह ज़्यादा concise और programmatically parse करने में आसान output देता है
    यह जानने की curiosity हुई कि कितनी commands में ज़्यादा machine-readable output होता है, और इसी से git-scm के “Git Internals - Plumbing and Porcelain” page तक पहुँच गया। संक्षेप में, Git शुरुआत से ही एक polished version control system के बजाय version control संभालने वाले tools के set की तरह लिखा गया था
    शुरुआत से Git इस्तेमाल करने वाले कई लोगों ने इन्हीं low-level commands से version control tasks सीखे, और उन workflows को दूसरों तक भी फैलाया। यही plumbing layer है। बाद में Git ने एक ज़्यादा refined layer बनाई और उसे porcelain कहा
    अभी मुझे पूरी तरह नहीं पता कि कौन-सी command किस layer में आती है, लेकिन इससे हाल के वर्षों में recommend किए जाने वाले नए workflows को समझने में मदद मिली है। अपना workflow बदलते समय भी बेहतर judgment कर पाता हूँ
    https://git-scm.com/book/en/v2/Git-Internals-Plumbing-and-Po...
    • यह साफ़ संकेत है कि Linus internal structure यानी plumbing से संतुष्ट थे, लेकिन UI यानी porcelain पर काम करने की ज़रूरत मानते थे। मूल रूप से porcelain सब ऐसे scripts थे जो plumbing को call करते थे
      अफ़सोस, इसे तेज़ बनाने के लिए उस UI को hardcode कर दिया गया, लेकिन improve नहीं किया गया
  • Julia की writing voice सच में बहुत अच्छी है। वह veteran developers के लिए भी बेहद valuable चीज़ें लिखती हैं, और साथ ही इस field में अभी-अभी आए लोगों के लिए भी approachable और inclusive tone बनाए रखती हैं
  • लगता है मुझे “Git Stockholm syndrome” हो गया है। ये terms मुझे इतनी उलझाने वाली नहीं लगतीं, लेकिन इसकी बड़ी वजह शायद यह है कि मैंने दूसरे systems लगभग सीखे ही नहीं और करीब 2011 से Git में गहराई से बंधा हुआ हूँ
    पीछे मुड़कर देखूँ तो शुरुआत करते समय यह बेहद confusing रहा होगा, लेकिन शायद cool दिखने के लिए मैंने ऐसा जताया कि नहीं है
    • Fossil version control system की CLI देखने के बाद मुझे एहसास हुआ कि मुझे Stockholm syndrome है। वह बहुत intuitive थी
    • Git से पहले मैंने cvs और svn इस्तेमाल किए थे, और svn की तुलना में Git समझना कहीं आसान था
    • मैंने जो दूसरा version control इस्तेमाल किया है वह केवल Plastic SCM है, और Stockholm syndrome हो या न हो, Git कहीं बेहतर है
  • साथ में देखने लायक: Git staging area सचमुच वह term है जिस पर सब सहमत हैं

https://news.ycombinator.com/item?id=28143078
“Your branch is up to date with ‘origin/main’” असल में थोड़ा misleading है। इसे ऐसे समझा जा सकता है कि main branch latest है, लेकिन असल में ऐसा नहीं है
हालांकि यहां बहुत ज़्यादा “technically speaking” जोड़ने की ज़रूरत नहीं है। क्या Two Generals Problem लागू नहीं होता? अगर सच में बहुत बारीकी से देखें, तो इसी पल यह “latest” है या नहीं, पता नहीं लगाया जा सकता। status से पहले fetch करने पर भी यही बात है
तो फिर reasonable expectation क्या होनी चाहिए? बस इतना कि मेरे computer के object database में मौजूद ref, पिछली बार check करने पर दूर कहीं मौजूद दूसरे object database के ref के बराबर था
एक simple status call network fetch नहीं कर सकती, न ही हर बार उस tool के basic principles याद दिला सकती है जिसे आप इस्तेमाल कर रहे हैं। निजी तौर पर मेरा यही मानना है। लेकिन हैरानी की बात है कि StackOverflow answer के कई comments को लगता है कि ये दोनों चीज़ें ज़रूरी हैं
“is up to date with the origin’s main as of your last fetch 5 days ago” जैसा wording थोड़ा ज़्यादा reasonable है। क्योंकि यह सिर्फ़ यह बताता है कि आख़िरी बार fetch किए कितना समय हो गया है
[1] https://stackoverflow.com/questions/27828404/why-does-git-st...
एक और बात: मुझे लगता था कि ORIG_HEAD, FETCH_HEAD की तरह “origin के head” से जुड़ा है। लेकिन ऐसा नहीं था। यह “pseudoref” rebase जैसे अधिक complex rewrite से पहले save point के तौर पर इस्तेमाल होता लगता है, और reflog आने से पहले implement किया गया था। शायद इसका मतलब “original head” है

  • मैं Git के प्रति काफ़ी sympathetic हूं, लेकिन उस message के wording पर लेखक से सहमत हूं। हालांकि उनके सुझाए alternative से सहमत नहीं हूं
    “Your branch is up to date with ‘origin/main’” technically सही है, लेकिन up to date expression को casually पढ़ने पर यह दो बातें imply करता है। main, origin/main जैसा है, और origin/main भी latest है—यानी command के दौरान update हुआ है या automatically latest रखा जाता है और हाल की sync सफल रही है
    यह कोई machine-readable signal नहीं है जिसे CPU के एक cycle तक true होना चाहिए, बल्कि user को दिखने वाला status message है। Network theory तक जाए बिना भी ऐसी interpretation reasonable है
    “Up to date” का मतलब space के बजाय time में catch up करना ज़्यादा लगता है। Local branch position “यह branch किसे point कर रही है” वाले space जैसी है, और remote ref state “मैंने remote ref को आख़िरी बार कब update किया” वाले time जैसी है। बेशक यह बहुत subjective है और दोनों अर्थ दोनों तरफ़ हो सकते हैं
    बेहतर wording “Your branch matches origin/main”, “Your branch’s head is the same as origin/main”, “Your branch is pointing to the same commit as origin/main” जैसी हो सकती है। यह clarity और verbosity के बीच compromise है। इसमें लेखक के सुझाव की तरह “remote ref last updated 5 days ago” को parentheses में भी जोड़ा जा सकता है
  • मैं इस बात से सहमत नहीं हूं कि status call का network fetch करना परेशान करने वाला है। मेरे हिसाब से network operations explicit होने चाहिए, implicit नहीं। जब मैं git status चलाता हूं, तो मुझे file system में मौजूद अपने repository की स्थिति जाननी होती है
    अगर मुझे जानना है कि किसी दूसरे remote पर क्या हो रहा है, तो मैं खुद fetch करके compare कर सकता हूं
  • उम्मीद यह होती है कि status command शुरू किए जाने के समय के आधार पर latest जानकारी मिले। जानकारी terminal में print होने के दौरान race condition हो सकती है, लेकिन वह बहुत छोटी time window है
    आम तौर पर इसका मतलब है कि आप fetch चाहते हैं। Two Generals Problem सिर्फ़ remote side पर लागू होती है। अगर remote को यह confirmation नहीं मिलता कि client ने data receive कर लिया है, तो वह कुछ समय तक retransmit करता रह सकता है। वह client की problem नहीं है
    अगर client को server से data नहीं मिलता, तो सही behavior शायद रुकना और timeout के बाद error print करना होगा; मौजूदा fetch शायद ऐसा ही करता है
  • Git सीखने में सबसे valuable step सही mental model बनाना है। सब कुछ graph है
    यह tool अक्सर share किया जाता है और यहां भी अच्छी तरह फिट बैठता है। यह Git के internal model और कई commands के effects को visualize करता है
    https://learngitbranching.js.org/
    इस tool को 10 मिनट इस्तेमाल करके मैंने जितना सीखा, वह उससे पहले के करीब 10 साल के Git experience से ज़्यादा था। Strongly recommend करता हूं
  • ज़्यादा जोड़ना नहीं चाहता, लेकिन Bitbucket वालों का pull request term बनाना भी problem है
    “pull” वह action है जिसमें remote changes को local repository में merge किया जाता है। User असल में जो request करता है, वह यह है कि server उसके remote changes को किसी branch में merge करे। GitLab का “merge request” सही expression है
    मैंने देखा है कि किसी ने fetch किया और commits गायब हो गए। Repository समय में पीछे चली गई थी, इसलिए वे छिप गए थे। Git ऐसी details को status में छिपा देता है, और अगर आप git-prompt या powerline-shell इस्तेमाल नहीं करते, तो आप अंधेरे में काम कर रहे हैं
    • git-request-pull(1) में बचा हुआ original idea यह था कि हम सबके अपने-अपने Git repositories kernel.org/git या redhat.com/git जैसी जगहों पर हों, और हम email से एक-दूसरे से अलग servers, organizations, domains में मौजूद repositories से pull करने का अनुरोध करें
      GitHub ने Git के request-pull command से inspiration लिया, लेकिन उसे एक GitHub repository से दूसरे GitHub repository में merge करने के रूप में reinterpret किया
    • Server के perspective से user remote है और server local है। इसलिए user server से request कर रहा है कि वह उसकी तरफ़ से pull करे
      कम से कम मैंने हमेशा इसे ऐसे ही पढ़ा है
    • Git book इस term की उत्पत्ति और यह क्यों समझ में आता है, समझाती है
      सार यह है कि यह server से की गई request नहीं, बल्कि किसी दूसरे व्यक्ति से की गई request है। जिस change से आप project में contribute करना चाहते हैं उसे देखने के लिए, आप सामने वाले से अपनी branch pull करने का अनुरोध करते हैं

[0] https://git-scm.com/book/en/v2/Distributed-Git-Contributing-...

  • “pull request” को GitHub ने लोकप्रिय बनाया, और मुझे यह ठीक-ठाक शब्द लगता है। असल में किसी दूसरे repository से pull किया जा रहा है या उसी repository के अंदर “merge request” किया जा रहा है—यह फर्क इतना दिलचस्प नहीं है। “merge request” GitLab के खास शब्द जैसा लगता है
  • यह मुझे हमेशा समझने में सबसे कठिन लगा। स्वाभाविक रूप से लगता है कि इसे pull request नहीं, बल्कि push request या merge request होना चाहिए