Git 進階指南

在掌握了基礎的 Git 使用 之后,可能會遇到一些問題。以下是貓哥篩選總結的部分常見問題,分享給各位朋友,掌握了這些問題的中的要點之后,git 進階也就完成了,它包含以下部分:

  • 如何修改 origin 倉庫信息
  • 如何配置 git ssh keys
  • 如何撤銷修改
  • 遇到沖突了怎么解決
  • git stash / alias / submodule 的使用問題等

問:如何修改 origin 倉庫信息?

1、添加 origin 倉庫信息

git remote add origin <git倉庫地址>

2、查看 origin 倉庫信息

# 以下三種方式均可
git config get --remote.origin.url
git remote -v
git remote show origin

3、刪除 origin 倉庫信息

git remote rm origin

問:如何配置 git ssh keys ?

  1. 在本地生成 ssh 私鑰 / 公鑰 文件
  2. 將「公鑰」添加到 git 服務(github、gitlab、coding.net 等)網站后臺
  3. 測試 git ssh 連接是否成功

接下來以添加 github ssh keys 為例,請注意替換 github 文件名。

注:如果對密鑰機制不熟悉,建議不要指定 -f 參數,直接使用默認的 id_rsa 文件名。

# 運行以下命令,一直回車,文件名可隨意指定
ssh-keygen -t rsa -b 4096 -C "kaiye@macbook" -f ~/.ssh/github

# 如果不是默認密鑰 id_rsa ,則需要以下命令注冊密鑰文件,-K 參數將密鑰存入 Mac Keychain
ssh-add -K ~/.ssh/github

# 將 pub 公鑰的內容粘貼到線上網站的后臺
cat ~/.ssh/github.pub

# 測試 git ssh 是否連接成功
ssh -T git@github.com

問:如何撤銷修改?

修改包含四種情況,需單獨區分。

1、新建的文件和目錄,且從未提交至版本庫

此類文件的狀態為 Untracked files ,撤銷方法如下:

git clean -fd .

其中,. 表示當前目錄及所有子目錄中的文件,也可以直接指定對應的文件路徑,以下其他情況類似。

2、提交過版本庫,但未提交至暫存區的文件(未執行 git add)

此類文件的狀態為 Changes not staged for commit,撤銷方法:

git checkout .

3、已提交至暫存區的文件

此類文件的狀態為 Changes to be committed,撤銷方法:

git reset .

執行之后文件將會回到以上的 1 或者 2 狀態,可繼續按以上步驟執行撤銷,若 git reset 同時加上 --hard 參數,將會把修改過的文件也還原成版本庫中的版本。

4、已提交至版本庫(執行了 git commit)

每次提交都會生成一個 hash 版本號,通過以下命令可查閱版本號并將其回滾:

git log
git reset <版本號>

如果需要「回滾至上一次提交」,可直接使用以下命令:

git reset head~1

執行之后,再按照 1 或者 2 狀態進行處理即可,如果回滾之后的代碼同時需要提交至 origin 倉庫(即回滾 origin 線上倉庫的代碼),需要使用 -f 強制提交參數,且當前用戶需要具備「強制提交的權限」。

5、如果回滾了之后又不想回滾了怎么辦?

如果是以上的情況 1 或者 2,只能歇屁了,因為修改沒入過版本庫,無法回滾。

如果是情況 4,回滾之后通過 git log 將看不到回滾之前的版本號,但可通過 git reflog 命令(所有使用過的版本號)找到回滾之前的版本號,然后 git reset <版本號> 。

問:遇到沖突了怎么解決?

兩個分支進行合并時(通常是 git pull 時),可能會遇到沖突,同時被修改的文件會進入 Unmerged 狀態,需要解決沖突。

1、最快的辦法

大部分時候,「最快解決沖突」的辦法是:使用當前 HEAD 的版本(ours),或使用合并進來的分支版本(theirs)。

# 使用當前分支 HEAD 版本,通常是沖突源文件的 <<<<<<< 標記部分,======= 的上方
git checkout --ours <文件名>

# 使用合并分支版本,通常是源沖突文件的 >>>>>>> 標記部分
git checkout --theirs <文件名>

# 標記為解決狀態加入暫存區
git add <文件名>

2、最通用的辦法

用編輯器打開沖突的源文件進行修改,可能會發生遺留,且體驗不好,通常需要借助 git mergetool 命令。

在 Mac 系統下,運行 git mergetool <文件名> 可以開啟配置的第三方工具進行 merge,默認的是 FileMerge 應用程序,還可以配置成 Meld 或 kdiff3,體驗更佳。

3、最好的習慣

有三個好的習慣,可以減少代碼的沖突:

  • 在開始修改代碼前先 git pull 一下;
  • 將業務代碼進行劃分,盡量不要多個人在同一時間段修改同一文件;
  • 通過 Gitflow 工作流 也可以提升 git 流程效率,減少發生沖突的可能性。

4、最復雜的情況

如果你的項目周期比較長,還應該養成「定期 rebase 的習慣」,git pull --rebase 可以讓分支的代碼和 origin 倉庫的代碼保持兼容,同時還不會破壞線上代碼的可靠性。

它的大概原理是,先將 origin 倉庫的代碼按 origin 的時間流在本地分支中提交,再將本地分支的修改記錄追加到 origin 分支上。如果發生沖突,則可以即時的發現問題并解決,否則到項目上線時再解決沖突,可能會發生額外的風險。

rebase 大概的操作步驟如下:

# 將當前分支的版本追加到從遠程 pull 回來的節點之后
git pull --rebase

# 若發生沖突,則按以上其他方法進行解決,解決后繼續
git rebase --continue

# 直到所有沖突得以解決,待項目最后上線前再執行
git push origin

# 若多次提交修改了同一文件,可能需要直接跳過后續提交,按提示操作即可
git rebase --skip

問:如何在不提交修改的前提下,執行 pull / merge 等操作?

有些修改沒有完全完成之前,可能不需要提交到版本庫,圡方法是將修改的文件 copy 到 git 倉庫之外的目錄臨時存放,pull / merge 操作完成之后,再 copy 回來。

這樣的做法一個是效率不高,另外一個可能會遺漏潛在的沖突。此類需求最好是通過 git stash 命令來完成,它可以將當前工作狀態(WIP,work in progress)臨時存放在 stash 隊列中,待操作完成后再從 stash 隊列中重新應用這些修改。

以下是 git stash 常用命令:

# 查看 stash 隊列中已暫存了多少 WIP
git stash list

# 恢復上一次的 WIP 狀態,并從隊列中移除
git stash pop

# 添加當前 WIP,注意:未提交到版本庫的文件會自動忽略,只要不運行 git clean -fd . 就不會丟失
git stash

# 恢復指定編號的 WIP,同時從隊列中移除
git stash pop stash@{num}

# 恢復指定編號的 WIP,但不從隊列中移除
git stash apply stash@{num}

問:如何在 git log 中查看修改的文件列表?

默認的 git log 會顯示較全的信息,且不包含文件列表。使用 --name-status 可以看到修改的文件列表,使用 --oneline 可以將參數簡化成一行。

git log --name-status --oneline

每次手動加上參數很麻煩,可以通過自定義快捷命令的方式來簡化操作:

git config --global alias.ls 'log --name-status --oneline --graph'

運行以上配置后,可通過 git ls 命令來實現「自定義 git log」效果,通過該方法也可以創建 git st 、 git ci 等一系列命令,以便沿用 svn 命令行習慣。

git config --global alias.st 'status --porcelain'

更多 git log 參數,可通過 git help log 查看手冊。

如果是看上一次提交的版本日志,直接運行 git show 即可。

此外,如果你的 Mac 安裝了 zsh(參考《全新 Mac 安裝指南(編程篇)》 ),那么可以直接使用大量內置 git 快捷命令,詳見此列表:Plugin:git ,其中較為常用的命令包括:

  • gl 即 git pull
  • gup 即 git pull --rebase,一般建議使用 gup,它會比 gl 少一次 merge 記錄
  • gst 即 git status
  • gaa 將當前版本庫所有改動提交至暫存區,即 git add -all
  • gp 本地分支提交至遠程倉庫,即 git push
  • gcmsg 即 git commit -m
  • gco 即 git checkout
  • glol 格式化版本號、提交時間、作者信息的 git log
  • gwip 臨時提交版本
  • gunwip 從當前分支的上一次臨時提交版本恢復修改

問:git submodule update 時出錯怎么解決?

例如,在執行 git submodule update 時有以下錯誤信息:

fatal: reference is not a tree: f869da471c5d8a185cd110bbe4842d6757b002f5
Unable to checkout 'f869da471c5d8a185cd110bbe4842d6757b002f5' in submodule path 'source/i18n-php-server'

在此例中,發生以上錯誤是因為 i18n-php-server 子倉庫在某電腦 A 的「本地」commit 了新的版本 「f869da471c5d8a185cd110bbe4842d6757b002f5」,且該次 commit 未 push origin。但其父級倉庫 i18n-www 中引用了該子倉庫的版本號,且將引用記錄 push origin,導致其他客戶機無法 update 。

解決方法,在電腦 A 上將 i18n-php-server 版本庫 push origin 后,在其他客戶機上執行 git submodule update 。或者用以上提到的 git reset 方法,將子倉庫的引用版本號還原成 origin 上存在的最新版本號。

其他問題

  • 設置本地分支與遠程分支保持同步,在第一次 git push 的時候帶上 -u 參數即可

    git push origin master -u 
    
  • 支持中文目錄與文件名的顯示(git 默認將非 ASCII 編碼的目錄與文件名以八進制編碼展示)

    git config core.quotepath off
    
  • 常用的打 tag 操作,更多請查看《Git 基礎 - 打標簽

    # 列出所有本地 tag
    git tag
    
    # 本地新增一個 tag,推送至 origin 服務器
    git tag -a v1.0.0 -m 'tag description'
    git push origin v1.0.0
    
    # 刪除本地與 origin tag
    git tag -d v1.0.0
    git push origin --delete v1.0.0
    
  • 使用 Git GUI 客戶端(如,SoureTree、Github Desktop)能極大的提升分支管理效率。分支合并操作通常只有兩種情況:從 origin merge 到本地,使用 git pull 即可;從另外一個本地分支 merge 到當前分支,使用 git merge <分支名>,以下是常用命令:

    # 新建分支 branch1,并切換過去
    git checkout -b branch1
    
    # 查看所有本地與遠程分支
    git branch -a
    
    # 修改完成后,切換回 master 分支,將 branch1 分支合并進來
    git checkout master
    git merge branch1
    
    # 刪除已完成合并的分支 branch1
    git branch -d branch1
    
  • Mac 下好用的 Git 對比、合并工具不多,推薦使用 Beyond Compare Pro Edition(付費軟件,多人團購有優惠),配置方法如下

    1. 從 Beyond Compare 主菜單中執行 Install Command Line Tools
    2. Shell 中運行如下 git 配置命令:
    git config --global diff.tool bc3
    # 設置完成后可使用 git difftool file.ext 對比文件歷史記錄
    
    git config --global merge.tool bc3
    git config --global mergetool.bc3 trustExitCode true
    git config --global mergetool.keepBackup false # 關閉生成 .orig 備份文件
    # 設置完成后可使用 git mergetool file.ext 合并沖突狀態的文件
    

    若使用 SourceTree 客戶端,設置與操作步驟如下:

    1. 配置外部對比、合并工具為 Beyond Compare
    sourceTree 配置外部對比、合并工具
    1. 使用指定合并工具解決沖突文件
    sourceTree 啟動合并工具解決沖突
    1. Beyond Compare 的合并界面,「上左」與「上右」面板為合并發生沖突的兩次提交版本,「上中」為前次歷史版本,「下方」為合并后的代碼。通常只需要處理下方面板中,「紅色!」所指示的代碼行,點擊「藍色?」或「紫色?」,選擇正確的代碼。合并完成后直接關閉窗口,文件會被自動標記為已解決狀態,添加至暫存區。
    Beyond Compare Merge 操作面板

如有其他問題,請在 github 上留言補充 :)

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,825評論 6 546
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,814評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,980評論 0 384
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 64,064評論 1 319
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,779評論 6 414
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 56,109評論 1 330
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 44,099評論 3 450
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 43,287評論 0 291
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,799評論 1 338
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,515評論 3 361
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,750評論 1 375
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,221評論 5 365
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,933評論 3 351
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,327評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,667評論 1 296
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,492評論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,703評論 2 380

推薦閱讀更多精彩內容

  • 1. 安裝 Github 查看是否安裝git: $ git config --global user.name "...
    Albert_Sun閱讀 13,699評論 9 163
  • 不知道還愛 不知道還恨 不知道什么是喜歡 不知道什么是愛 不知道明天還在 不知道你是誰 不知道歲月不饒人 不知道有...
    大濕人閱讀 186評論 0 0
  • 春三月,此謂發陳,天地俱生,萬物以榮,夜臥早起,廣步于庭,被發緩形,以使志生,生而勿殺,予而勿奪,賞而勿罰,此春氣...
    錦似半夏閱讀 327評論 0 1
  • 三個月相處 讓我更相信你們 從最初的不開心 到現在的其樂融融 雖然現在我們不會別離 但我已開始想戀 現在一別 不知...
    寫作星閱讀 330評論 0 0