『Git 干貨』#2 本地倉庫使用(簡明)

訪問博客查看 本文 最新內(nèi)容,排版更美觀ヾ(?ω?`)o 如有錯誤歡迎指出~

Git 系列學(xué)習(xí)筆記:

接上文,本文在命令行的基礎(chǔ)上介紹了常用指令的在本地的使用情景疮跑。

本文大部分內(nèi)容參考了 RCY 同學(xué)的教程静袖,部分參考了 廖雪峰教程-Git烂完,菜鳥教程-Git贾陷,以及 Git 官網(wǎng)文檔 Git-Documentation疮绷。

本地的 Git

預(yù)先準(zhǔn)備

在正式的操作前弧关,你需要先配置你的用戶信息盅安,這件事情通常在你的機器上只需要干一次即可,因為我們使用了全局配置世囊。在任意?個目錄打開你的終端别瞭,配置你的用戶名和郵箱:

$ git config --global user.name <username> # 替換為 GitHub 用戶名
$ git config --global user.email <email>   # 替換為綁定的郵箱
# username 中如果有空格,需要加雙引號

基本操作

在想用 Git 管理的項目路徑下右鍵進入 Bash 終端株憾,然后將當(dāng)前目錄初始化為 Git 倉庫蝙寨。

$ git init

手動新建一個文件,隨便寫點什么嗤瞎,譬如一個 hello.md墙歪,此時文件存在于工作區(qū)。下面將其跟蹤并提交:

$ git add hello.md      # 如果有更多文件贝奇,也可直接追加在后面
$ git commit -m "Init"  # -m: 表示 message虹菲,備注本次提交信息

注意到,add 后面是文件名掉瞳,也可以是目錄毕源、通配符髓帽,因此也支持以下寫法:

$ git add .          # 相對路徑中 . 表示當(dāng)前目錄,因此這一選項會添加當(dāng)前目錄下所有文件
$ git add *.cpp      # * 代表任意字符串脑豹,所有 .cpp后綴的文件被添加
$ git add test?.cpp  # ? 代表單個字符郑藏,不得為空,因此如 test1.cpp 將被添加瘩欺,而 test.cpp 等不會
$ git add dir/       # 添加路徑下的 d 文件夾內(nèi)全部文件必盖, / 有沒有皆可

此外,為了體現(xiàn)三個區(qū)俱饿,我們可以使用一些指令來對比:

$ git status         # 查看工作區(qū)歌粥、暫存區(qū)的文件,一般前者是紅色拍埠,后者是綠色
$ git diff           # 查看工作區(qū)和暫存區(qū)的差異失驶,適用于暫存后又修改的內(nèi)容
$ git diff --cached  # 查看暫存區(qū)與 Git 倉庫的差異,適用于提交前查看
$ git diff HEAD      # 同時查看其他兩個區(qū)和 Git 倉庫的差異
Diff用法圖解

在工程中枣购,通常我們不用命令行查看差異嬉探,而是用 VSCode、GitHub Desktop棉圈、GitLab 等可視化工具涩堤。

如果對于已暫存的文件后悔了,也可以取消暫存:

$ git reset <filename>  # 對于該命令分瘾,如果不帶參數(shù)則會清空暫存區(qū)
$ git restore --stage <filename>

在完成了幾次提交后胎围,可以查看提交歷史:

$ git log

提交歷史中,每個提交記錄都有對應(yīng)的 commit hash 值德召,唯一標(biāo)識了這次提交白魂,這是 Git 用 SHA-1 hash 生成的加密字符串。

注:如果 log 比較長或者窗口比較小上岗,這會觸發(fā)「導(dǎo)航」模式福荸,很多人第?次見到可能不知所措,不會退出該頁面液茎,此時可以:

  • 上下鍵移動或 Page Up / Down 翻頁逞姿;
  • 輸入 \ 接字符來全局查找 ;
  • 輸入 q 退出捆等,與其他系統(tǒng)中的導(dǎo)航模式類似滞造;
  • 其他操作可以通過查詢關(guān)鍵字「Linux less 導(dǎo)航」來查到。

分支 (Branch)

有了前面的知識栋烤,我們已經(jīng)在腦海中想象?副快照變更圖了谒养,本節(jié)中我們將快照稱作「結(jié)點」,若干結(jié)點組織成了版本樹——Git 本身正是使用了紅黑樹對結(jié)點進行高效管理。

以下內(nèi)容強烈推薦結(jié)合 Git 分支在線教程 來學(xué)習(xí)买窟!

目前我們的結(jié)點樹基本是串行的(除了回退丰泊、重新提交會導(dǎo)致分叉),那么所謂的并行開發(fā)如何體現(xiàn)呢始绍?

注意到了反復(fù)有?個單詞 main 出現(xiàn)在命令行瞳购,這即是 Git 默認(rèn)的分支:主分支(舊版本叫 master)。main 即是這個分支的名字亏推,也是一個指針学赛,指向了該分支的最新結(jié)點。

和它?起的還有?個單詞 HEAD吞杭,這表示頭指針盏浇,指向當(dāng)前所處的結(jié)點。在你做分支相關(guān)的操作前芽狗,會有 HEAD -> main -> 最新結(jié)點绢掰,直到你將它們分開。

創(chuàng)建分支

與初始化倉庫類似童擎,創(chuàng)建分支也很方便:

$ git branch test  # 創(chuàng)建?個名為 test 的分?

注意:創(chuàng)建完后分支的即會指向當(dāng)前所在的結(jié)點滴劲,因此當(dāng)前最新結(jié)點同時被 main、test柔昼、HEAD 指向哑芹,即 HEAD -> main(test) -> 最新結(jié)點

對于已有的分支捕透,也可以通過以下命令查看、切換:

$ git branch         # 查看本地分支碴萧,帶 * 的為 HEAD 指向的當(dāng)前分支
$ git checkout test  # 檢出乙嘀,表示切換到 test 分支

# 上述的創(chuàng)建、切換操作也可以被縮減為一步操作
$ git checkout -b test # 創(chuàng)建?個名為 test 的分?并且切換過去

切換分支后破喻,可以看到出現(xiàn)在命令行右側(cè)的 main 已經(jīng)變成了 test虎谢。查看 log 也可發(fā)現(xiàn) HEAD -> test(main) -> 最新結(jié)點

合并分支

如果此時我們已經(jīng)在不同的分支提交了不同修改 C2 和 C3曹质,那么如何將分支合并到一起婴噩,使得并行開發(fā)結(jié)果匯總呢?

$ git checkout main  # 切換到 main 分?
$ git merge test     # 讓 main 分?合并 test 分?的結(jié)點

對于分支的合并羽德,Git 有專門的圖形化輸出命令來進行查看版本樹(也可以用其他可視化工具):

$ git log --graph --oneline --all
# oneline 表示用行來顯示記錄几莽,最上方的是最新的提交
# all 表示顯示所有分支,如果沒有則只顯示當(dāng)前分支及其祖先

# 當(dāng)然宅静,還有其他許多參數(shù)可以美化版本樹章蚣,這里貼一個大神的版本
$ git log --graph --all --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit --date=relative

為展示方便,這里使用在線教程里的圖例:

main分支合并test分支

可以看到姨夹,合并后產(chǎn)生了一個新結(jié)點 C4纤垂,該結(jié)點具有雙父結(jié)點矾策,指向原來的 C2 和 C3。需要注意的是峭沦,該結(jié)點屬于 main 分支贾虽,是 main 分支的最新結(jié)點(被指針 main 所指),而 test 仍指向舊的 C2吼鱼。

如果要把 test 分支也同步到新結(jié)點蓬豁,只需要讓 test 分支合并 C4,也就是合并當(dāng)前的 main 分支:

$ git checkout test  # 切換到 test 分?
$ git merge main     # 讓 test 分?合并 main 分?的結(jié)點

而由于 main 分支的最新結(jié)點 C4 繼承自 C2蛉抓,此時的 Git 不會有任何操作庆尘,只是簡單地將指針 test 移動到指針 main 所在位置,即快速前移(fast-forward):

test分支合并main分支

多數(shù)情況下巷送,我們會先用主分支合并從分支驶忌,如果之后需要再從分支繼續(xù)開發(fā),才會把從分支快速前移笑跛!

沖突的合并

如果 C2 和 C3 修改的代碼不在同一文件的同一處付魔,上述的 merge 是沒有問題的,但是一旦發(fā)生沖突飞蹂,git merge test 命令時就會提示錯誤几苍。

此時如果我們用 git status 查看,會發(fā)現(xiàn)工作區(qū)里有一個新的狀態(tài)「未合并的路徑」陈哑,里面就是沖突的文件妻坝。打開該文件,會發(fā)現(xiàn) Git 已經(jīng)在里面標(biāo)記出了雙方修改的內(nèi)容(用 VSCode 等 IDE 將看得更清楚)惊窖。

而我們只需要手動維護沖突刽宪,將該文件手動加入暫存區(qū),最后再提交界酒,就會生成一個新的結(jié)點圣拄,該結(jié)點無異于直接使用 git merge test 命令得到的。

變基 (Rebase)

一個來回穿插的版本樹是有點凌亂的毁欣,此時不得不提到第二種合并分支的辦法:變基 (rebase) 操作庇谆。Rebase 實際上就是取出從分支的提交記錄,「復(fù)制」它們凭疮,然后在主分支逐個的放下去饭耳。

Rebase 的優(yōu)勢就是可以創(chuàng)造更線性的提交歷史。如果兩個分支沒有沖突哭尝,如上文提到的第一種情況哥攘,直接 Merge 會出現(xiàn)一個新的結(jié)點(實際上該結(jié)點并沒有做出實質(zhì)的修改,反而使版本樹變得冗長)。

此時如果我們用 Rebase 操作逝淹,則可以簡化版本樹:

$ git checkout test  # 切換到 test 分?
$ git rebase main    # 讓 test 分?以 main 為基耕姊,因此 test 成為 main 的后代

注意,Rebase 操作通常是讓從分支變基到主分支栅葡,這與 Merge 操作是相反的茉兰!

test分支變基到main

觀察該圖,我們可以發(fā)現(xiàn) test 分支上的工作在 main 的最頂端欣簇,同時我們也得到了一個更線性的提交序列规脸。

而提交記錄 C2 依然存在(樹上那個半透明的節(jié)點),而 C2’ 是我們 Rebase 到 main 分支上的 C2 的副本熊咽,它們具有不同的 hash 值莫鸭,可以通過 log 查看。

之后我們也可以通過類似的操作横殴,把 main 快速前移到最新的結(jié)點:

$ git checkout main  # 切換到 main 分?
$ git rebase test    # 讓 main 分?以 test 為基被因,快速前移
# 當(dāng)然,z也可以用前面的 merge 操作

Rebase 操作在沒有沖突時將非常舒適衫仑,可以避免沒有意義的合并結(jié)點(尤其是涉及到遠(yuǎn)程倉庫時)梨与,但是一旦發(fā)生了沖突,操作將十分繁瑣文狱!這里不再贅述粥鞋,具體工程中如果遇到了請根據(jù) Git 的自動提示逐步操作。

而對于 Rebase 后的從分支上的結(jié)點瞄崇,就變成了所謂的「懸垂結(jié)點」呻粹,這些結(jié)點的訪問將十分復(fù)雜。此外苏研,如果這個從分支被廢棄尚猿,我們也可以用以下指令將其刪去:

$ git branch -d test  # 刪除名為 test 的分?,用于合并后廢棄的分支

分叉 (Branch Diverged)

分叉是分支的一種特殊情況楣富,往往是因為某些「不友好」操作而產(chǎn)生,最終被廢棄掉伴榔。對于單人操作的倉庫纹蝴,其產(chǎn)生原因可能是:

  • Reset 后舊分支:版本回退后重新提交,這種情況下往往是要棄用舊分支踪少。但如果舊的分支仍有需要保留的更改塘安,則需要 Cherry-Pick 等操作。
  • Rebase 后從分支:上文介紹到援奢,Rebase 將創(chuàng)造更線性的主分支兼犯,但這樣做的代價是從分支將被廢棄,成為一個無用的分叉。

上述情形的發(fā)生往往可以人為進行控制切黔,而對于多人操作的倉庫砸脊,如果不同開發(fā)者同時對一個結(jié)點進行了更改,將會造成「不可控」的分叉纬霞,具體情形及解決方法將在下一節(jié)介紹凌埂。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市诗芜,隨后出現(xiàn)的幾起案子瞳抓,更是在濱河造成了極大的恐慌,老刑警劉巖伏恐,帶你破解...
    沈念sama閱讀 222,104評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件孩哑,死亡現(xiàn)場離奇詭異,居然都是意外死亡翠桦,警方通過查閱死者的電腦和手機横蜒,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,816評論 3 399
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來秤掌,“玉大人愁铺,你說我怎么就攤上這事∥偶” “怎么了茵乱?”我有些...
    開封第一講書人閱讀 168,697評論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長孟岛。 經(jīng)常有香客問我瓶竭,道長,這世上最難降的妖魔是什么渠羞? 我笑而不...
    開封第一講書人閱讀 59,836評論 1 298
  • 正文 為了忘掉前任斤贰,我火速辦了婚禮,結(jié)果婚禮上次询,老公的妹妹穿的比我還像新娘荧恍。我一直安慰自己,他們只是感情好屯吊,可當(dāng)我...
    茶點故事閱讀 68,851評論 6 397
  • 文/花漫 我一把揭開白布送巡。 她就那樣靜靜地躺著,像睡著了一般盒卸。 火紅的嫁衣襯著肌膚如雪骗爆。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,441評論 1 310
  • 那天蔽介,我揣著相機與錄音摘投,去河邊找鬼煮寡。 笑死,一個胖子當(dāng)著我的面吹牛犀呼,可吹牛的內(nèi)容都是我干的幸撕。 我是一名探鬼主播,決...
    沈念sama閱讀 40,992評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼圆凰,長吁一口氣:“原來是場噩夢啊……” “哼杈帐!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起专钉,我...
    開封第一講書人閱讀 39,899評論 0 276
  • 序言:老撾萬榮一對情侶失蹤挑童,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后跃须,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體站叼,經(jīng)...
    沈念sama閱讀 46,457評論 1 318
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,529評論 3 341
  • 正文 我和宋清朗相戀三年菇民,在試婚紗的時候發(fā)現(xiàn)自己被綠了尽楔。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,664評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡第练,死狀恐怖阔馋,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情娇掏,我是刑警寧澤呕寝,帶...
    沈念sama閱讀 36,346評論 5 350
  • 正文 年R本政府宣布,位于F島的核電站婴梧,受9級特大地震影響下梢,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜塞蹭,卻給世界環(huán)境...
    茶點故事閱讀 42,025評論 3 334
  • 文/蒙蒙 一孽江、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧番电,春花似錦岗屏、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,511評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至洼冻,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間隅很,已是汗流浹背撞牢。 一陣腳步聲響...
    開封第一講書人閱讀 33,611評論 1 272
  • 我被黑心中介騙來泰國打工率碾, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人屋彪。 一個月前我還...
    沈念sama閱讀 49,081評論 3 377
  • 正文 我出身青樓所宰,卻偏偏與公主長得像,于是被迫代替她去往敵國和親畜挥。 傳聞我的和親對象是個殘疾皇子仔粥,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,675評論 2 359

推薦閱讀更多精彩內(nèi)容