大家好,歡迎來到周一git專題。
git clone
在上一篇文章當中我們聊了怎么在github當中創建一個屬於自己的項目(repository),簡稱repo。除了建立自己的repo之外,我們更多的情況是拷貝別人的repo,這樣才可以獲得別人整理好的代碼資料什么的,也更符合開源(白嫖)精神嘛。
這也不是什么難題,相信很多人都知道,當我們想要獲取其他人的repo的時候,可以通過git clone命令進行拉取。比如你想要獲取我們這個教程的repo,可以通過下面這個命令。
git clone git@github.com:moutsea/git-tutorial.git
這個命令我們都知道,通過git clone再加上repo的地址就可以了。但是這里的地址是哪里來的呢?簡單介紹一下,這是在github當中找到的。我們點擊Code那個綠色按鈕,在下方的彈框里點擊一下,就可以復制下來。一般情況下我們默認使用SSH協議,如果你看過我們上篇文章的話,你一定知道我在說什么。當然你也可以用HTTPS。

還有一個問題是我們clone下來的這個repo它存在哪里呢?答案也很簡單,就是我們在哪里運行的命令它就存在哪里。
另外再說一個小技巧,我們這樣clone下來之后會在我們本地新建一個文件夾,然后把這個repo當中的內容存在里面。這個文件夾的名字默認是這個repo的名字,如果你不喜歡這個名字,也可以在命令當中進行設置,設置的方法也很簡單,就是在命令最后加上一個你想要起的名字。
比如這樣,你得到的文件夾就是TechFlow。
git clone git@github.com:moutsea/git-tutorial.git techflow
git 四大狀態
即使是git新手應該也都知道git三板斧,也就是常說的git add,git commit和git push。但是當我們使用這些命令的時候,有沒有想過我們為什么要用這些命令呢?它們究竟代表了什么含義,這么做的意義是什么,如果我們不這么干又會發生什么?
如果我只是簡單地告訴你git add就是添加,git commit就是提交,那么其實一點用也沒有,和沒說一樣。因為關於git底層的運行機制一點也沒提,我們也不知道為什么要添加,要提交,提交了添加了意味着什么。所以要解釋清楚git這三板斧的原理,需要我們做一些更細致地解釋,至少需要把git內部的四個狀態講清楚。
在我們進行這一段之前,首先和大家明確一個概念,就是git系統和我們計算機當中的文件系統其實是兩碼事。雖然git有很多神奇的操作,可以自由地回滾或者是創建文件,但它們依然是兩套系統。git並不會自發地感知文件系統當中文件的變更,除非我們執行相關的命令。可以理解為它是被動響應的,畢竟git只是我們安裝的一個軟件,並不是操作系統的一部分。
這一點看似是廢話,但是是很重要的基礎,如果沒搞明白,后面會產生很多疑惑。
我們繼續來說git內部的狀態,這四個狀態分別是untrack,modified,committed和staged。之所以用英文,是為了大家以后閱讀其他文檔不會產生歧義。因為大家翻譯的譯名可能有多個版本,這會導致歧義。下面來簡單介紹一下這幾個狀態分別意味着什么。
untrack
首先是untrack,untrack我們直譯就可以了。track有軌道以及記錄的意思,所以untrack就是還沒記錄。那么什么樣的東西是還沒記錄的呢?比如可以想到新生兒,剛出生的新生兒名字都沒有,當然也沒有記錄在案,所以需要登記一下人口。那么在登記之前,就可以認為這些新生兒是untrack的。
遷移到開發當中來,我們新創建的文件其實就是系統里的“新生兒”。在我們將它們記錄在案之前,它們的狀態就是untrack。所以當你在一個git項目當中新建了文件的時候,如果你用git status命令去查看git當中的狀態,就會看到系統會提示你有些文件狀態是untrack。

這里的展示是亂碼,是因為我用的中文。這一串亂碼就是“第三篇”的意思。我們可以注意到,在輸出的結果最后一行,系統提示我們可以用git add命令來track它。這個也是git很人性化的一點,很多時候它會提醒我們可以使用什么命令做成什么樣的事情。所以大家千萬不要忽視這些日志,里面的信息是很重要的。
modified
下一個說的狀態是modified,modified顧名思義就是修改過的意思。針對的就是已經登記在案的文件最近又發生了改動的情況,也就是說我們最近改過了某一個之前已經登記在案的文件,那么當我們查看狀態的時候得到的就是modified,表示改動了,之前的記錄已經不是最新的了,我們需要更新。
同樣,我們可以通過git status命名來查看modified的情況。

我們看最下方的紅字,它說的是“第三篇”這個文件我們已經有了新的改動,可以使用git add命令來將它更新,或者是使用git restore命令來取消這個文件的登記信息,也就是讓他回到“新生兒”的狀態。
staged
接下來介紹的狀態是staged,它沒有很好的翻譯,可以大概理解成暫存。也就是說我們把所有的改動都記錄下來了,現在git系統當中記錄的已經是這個文件最新的狀態了。
當我們創建了新的文件,或者是有了新的改動,執行git add之后,得到的狀態就是staged。這個時候當我們執行git status,就會看到我們當下創建和更新了哪些文件。注意在所有的改動都暫存的情況下,git status是不會出現紅色的提示的,只會有綠色的提示信息。

當然這里的文字之所以有顏色是因為我使用了zsh這個終端,如果不配置是沒有的,就只能看到白色的的文字。zsh這個終端只在Linux和MacOS當中有,windows沒有。而win的終端和系統一直被程序員們吐槽難用,建議有條件的同學可以研究一下Linux,裝個虛擬機也好。
當我們終端沒有顏色高亮的時候,就只能通過上面的文本來判斷了,如果出現了Untracked files或者是Changes to be committed這些提示語的話,說明你還有改動沒有同步到git當中來,可以通過git add命令完成。
committed
最后講的一個狀態就是committed,這個committed表示的已提交。前面說了staged只是暫存,還沒有真正提交進git系統當中。只有通過命令git commit之后,才算是真正把暫存區的代碼提交了。經過git commit命令之后,所有被提交的文件的狀態就是committed。
這個時候如果我們執行git status再來查看,會看到提示nothing to commit, working tree clean.

這就表示我們所有的改動都已經提交進本地的git倉庫當中了,以后及時我們不小心刪錯了代碼,或者是做了一些修改。只要本地的git倉庫還在,這些代碼就都還可以找得回來。一直到這里為止,我們所有的操作都是離線的,都不需要網絡參與。這也是我們前文說的git的一個優點之一。
git commit之后,我們就可以通過git push來把本地的改動同步到遠程了。當然這一步是肯定需要網絡的,並且也可能會遇到很多問題,其中也有很多細節,我們之后再詳細展開。
我們用一張圖來總結一下上面提到四種狀態,以及git的整個工作流來加深一下印象。

總結
看完了上面關於git狀態的介紹之后,想必大家就可以明白,我們在使用git的時候,最常用的三板斧也就是git add,git commit以及git push的命令究竟是干嘛的了。
git add可以把所有的改動,無論是修改的還是新建的都存入暫存區。git commit可以將暫存區的改動提交到本地git倉庫,最后git push可以把本地倉庫的改動同步到遠端。看起來好像平平無奇對吧,但我們仔細琢磨會發現一個很奇怪的點,那就是既然我們git add和git commit都是提交,只不過是提交的目的地不同,一個是暫存區一個是本地倉庫。那么為什么我們不能直接將它們合並呢?我們git add就是直接提交到本地倉庫不行嗎?
實際上SVN這個版本控制工具就是這么做的,但是這有一個問題就是當我們提交的時候,它會讓我們選擇我們要提交的文件。如果改動量小還好,如果改動量很大,我們要手動去一個一個輸入需要提交的文件顯然是一個非常麻煩的事情。而有了暫存區之后,我們就可以在開發的時候,一邊開發一個邊把文件提交到暫存區,最后直接一起commit到倉庫就可以了。就可以避免最后提交之前的麻煩了,因為反正提交這個操作一定是原子的,要么全部成功,要么全部失敗,是不允許部分成功這種情況發生的。
而且很多極客更加喜歡在終端環境當中操作代碼,而不是在一個彈出來的界面里點點點,這會讓他們覺得非常不極客(逼格太低)。有了暫存區之后就可以很方便地做到這一點。
到這里,我們的文章就結束了,感謝您的閱讀。相信看完之后,對於git當中的狀態以及它們的作用應該有了一個基礎的了解,並且應該還學到了一個裝逼技能,就是問你的小伙伴,你知道為什么git里有一個暫存區而SVN里沒有嗎?因為不極客。
衷心祝願大家每天都有所收獲。如果還喜歡今天的內容的話,請來一個三連支持吧~(點贊、在看、轉發)
本文使用 mdnice 排版
- END -