git日常使用教程
目錄
- git日常使用
- git 基礎(chǔ)用法(本地)
- git branch
- git checkout
- git merge
- git rebase
- HEAD ,在提交樹上移動
- 相對引用
- 強(qiáng)制修改分支位置
- 撤銷變更
- 整理提交記錄
- 提交技巧
- Git Tags
- Git Describe
- git 基礎(chǔ)用法(遠(yuǎn)程)
- git fetch
- git pull
- git push
- 偏離的提交歷史,十分重要!!!
- 配置參數(shù)選項(xiàng)
- merge 與 rebase的選擇
- 更新倉庫提交歷史
- 合并多個commit提交記錄
- 刪除意外調(diào)試的測試代碼
- 如何處理工作中斷
git日常使用
參考網(wǎng)站:Git 實(shí)用技巧記錄
和學(xué)習(xí)git
日常使用git的流程如下
當(dāng)修改完代碼,將本次修改的代碼提交到遠(yuǎn)端流程:
# 工作區(qū) -> 暫存區(qū) git add <file/dir> # 暫存區(qū) -> 本地倉庫 + 注釋 git commit -m "memo" # 本地倉庫 -> 遠(yuǎn)程倉庫 git push origin master # 本地 master 分支推送到遠(yuǎn)程 origin 倉庫拉取遠(yuǎn)端最新版本代碼到本地流程:
# 本地倉庫 <- 遠(yuǎn)程倉庫 git clone <git_url> # 克隆遠(yuǎn)程倉庫 git fetch upstream master # 拉取遠(yuǎn)程代碼到本地但不應(yīng)用在當(dāng)前分支 git pull upstream master # 拉取遠(yuǎn)程代碼到本地并且應(yīng)用在當(dāng)前分支 git pull --rebase upstream master # 如果平時使用 rebase 合并代碼則加上 # 暫存區(qū) <- 本地倉庫 git reset HEAD <file> # 本地倉庫文件內(nèi)容覆蓋暫存區(qū)文件內(nèi)容 # 工作區(qū) <- 暫存區(qū) git checkout -- <file> # 暫存區(qū)文件內(nèi)容覆蓋工作區(qū)文件內(nèi)容將本地倉庫代碼覆蓋到工作區(qū)的流程:
# 工作區(qū) <- 本地倉庫 git reset <commit> # 本地倉庫覆蓋到工作區(qū)(保存回退文件內(nèi)容修改) git reset --mixed <commit> # 同上 git reset --soft <commit> # 本地倉庫覆蓋到工作區(qū)(保留修改并加到暫存區(qū)) git reset --hard <commit> # 本地倉庫覆蓋到工作區(qū)(不保留修改直接刪除掉)git 基礎(chǔ)用法(本地)
git branch
創(chuàng)建一個新的分支
git branch your-branch-namegit checkout
創(chuàng)建一個新的分支的同時切換到新創(chuàng)建的分支:
git checkout -b your-branch-namegit merge
將兩個分支合并在一起
下面這個是將bugFix分支合并到master上
如果你出現(xiàn)這個情況:
可以使用命令:
刪除所有隱藏的版本
git rebase
還有一種合并分支的方法是git rebase,實(shí)際上就是取出一系列的提交記錄,復(fù)制它們,然后在另外一個地方逐個放下去。
我們想要把 bugFix 分支里的工作直接移到 master 分支上。移動以后會使得兩個分支的功能看起來像是按順序開發(fā),但實(shí)際上它們是并行開發(fā)的。注意,提交記錄 C3 依然存在(樹上那個半透明的節(jié)點(diǎn)),而 C3’ 是我們 Rebase 到 master 分支上的 C3 的副本。
之后切換master然后把它rebase到bugFix分支上。
HEAD ,在提交樹上移動
HEAD 是一個對當(dāng)前檢出記錄的符號引用 —— 也就是指向你正在其基礎(chǔ)上進(jìn)行工作的提交記錄。
HEAD 總是指向當(dāng)前分支上最近一次提交記錄。大多數(shù)修改提交樹的 Git 命令都是從改變 HEAD 的指向開始的。
使用git checkout hashvalue可以指向?qū)?yīng)的版本
相對引用
通過指定提交記錄哈希值的方式在 Git 中移動不太方便,實(shí)際使用時你就不得不用 git log 來查查看提交記錄的哈希值。并且哈希值在真實(shí)的 Git 世界中也會更長。Git 對哈希的處理很智能。你只需要提供能夠唯一標(biāo)識提交記錄的前幾個字符即可。
使用相對引用的話,你就可以從一個易于記憶的地方(比如 bugFix 分支或 HEAD)開始計(jì)算。使用方法如下:
- 使用 ^ 向上移動 1 個提交記錄
- 使用 ~ 向上移動多個提交記錄,如 ~3
強(qiáng)制修改分支位置
相對引用使用的最多的就是移動分支,可以使用 -f 讓分支指向另一個提交:
# 將master分支強(qiáng)制指向HEAD的第3級父提交 git branch -f master HEAD^3撤銷變更
主要有兩種方法用來撤銷變更:
一是 git reset,還有就是 git revert。
git reset 通過把分支記錄回退幾個提交記錄來實(shí)現(xiàn)撤銷改動。你可以將這想象成“改寫歷史”。git reset 向上移動分支,原來指向的提交記錄就跟從來沒有提交過一樣。
在reset后, 之前 所做的變更還在,但是處于未加入暫存區(qū)狀態(tài)。
雖然在你的本地分支中使用 git reset 很方便,但是這種“改寫歷史”的方法對大家一起使用的遠(yuǎn)程分支是無效的。
為了撤銷更改并分享給別人,我們需要使用git revert HEAD
在我們要撤銷的提交記錄后面多了一個新提交。這是因?yàn)樾绿峤挥涗?C2’ 引入了更改 —— 這些更改剛好是用來撤銷 C2 這個提交的。也就是說 C2’ 的狀態(tài)與 C1 是相同的。revert 之后就可以把你的更改推送到遠(yuǎn)程倉庫與別人分享啦。
整理提交記錄
開發(fā)人員有時會說“我想要把這個提交放到這里, 那個提交放到剛才那個提交的后面”, 而接下來就講的就是它的實(shí)現(xiàn)方式。
第一個命令:
如果你想將一些提交復(fù)制到當(dāng)前所在的位置(HEAD)下面的話, Cherry-pick 是最直接的方式了。
將 side 分支上的工作復(fù)制到 master 分支:
| 圖1 | 圖2 |
當(dāng)我們不清楚提交記錄的哈希值時,可以利用交互式rebase:
交互式 rebase 指的是使用帶參數(shù) --interactive 的 rebase 命令, 簡寫為 -i
如果你在命令后增加了這個選項(xiàng), Git 會打開一個 UI 界面并列出將要被復(fù)制到目標(biāo)分支的備選提交記錄,它還會顯示每個提交記錄的哈希值和提交說明,提交說明有助于你理解這個提交進(jìn)行了哪些更改。
在實(shí)際使用時,所謂的 UI 窗口一般會在文本編輯器 —— 如 Vim —— 中打開一個文件。
當(dāng) rebase UI界面打開時, 你能做3件事:
- 調(diào)整提交記錄的順序(通過鼠標(biāo)拖放來完成)
- 刪除你不想要的提交(通過切換 pick 的狀態(tài)來完成,關(guān)閉就意味著你不想要這個提交記錄)
- 合并提交。 它允許你把多個提交記錄合并成一個。
| 圖1 | 圖2 |
提交技巧
情景一:
你之前在 newImage 分支上進(jìn)行了一次提交,然后又基于它創(chuàng)建了 caption 分支,然后又提交了一次。
此時你想對的某個以前的提交記錄進(jìn)行一些小小的調(diào)整。
我們可以通過下面的方法來克服困難:
- 先用git rebase -i將提交重新排序,然后把我們想要修改的提交記錄挪到最前
- 然后用commit --amend來進(jìn)行一些小的修改
- 接著再用git rebase -i來將他們調(diào)回原來的順序
- 最后把master以到修改的最前端就可以了
例如下面:
使用命令:
| 圖1 | 圖2 |
情景二
仍然是上面的要求,不過rebase的問題就是要進(jìn)行兩次排序,而這有可能造成由 rebase 而導(dǎo)致的沖突。下面我們使用git cherry-pick:
cherry-pick 可以將提交樹上任何地方的提交記錄取過來追加到 HEAD 上(只要不是 HEAD 上游的提交就沒問題)。
| 圖1 | 圖2 |
Git Tags
tag主要用于發(fā)布版本的管理,一個版本發(fā)布之后,我們可以為git打上 v.1.0.1 v.1.0.2 …這樣的標(biāo)簽。
建立一個標(biāo)簽,指向提交記錄C1,表示這是我們的1.0版本
注意,如果你不指定提交記錄,Git 會用 HEAD 所指向的位置。
| 圖1 | 圖2 |
Git Describe
標(biāo)簽在代碼庫中起著“錨點(diǎn)”的作用,Git 還為此專門設(shè)計(jì)了一個命令用來描述離你最近的錨點(diǎn)(也就是標(biāo)簽),它就是 git describe
語法如下:
可以是任何能被git識別成提交記錄的引用,如果沒有指定的話,會以目前所檢出的位置(HEAD)
輸出結(jié)果為:
<tag>_<numCommits>_g<hash>
tag表示的是離ref最近的標(biāo)簽,numCommits表示的是這個ref與tag相差多少個提交記錄,hash表示的是你所給定的 ref 所表示的提交記錄哈希值的前幾位。
我們對如下分支進(jìn)行describe:
git 基礎(chǔ)用法(遠(yuǎn)程)
Git 遠(yuǎn)程倉庫相當(dāng)?shù)牟僮鲗?shí)際可以歸納為兩點(diǎn):向遠(yuǎn)程倉庫傳輸數(shù)據(jù)以及從遠(yuǎn)程倉庫獲取數(shù)據(jù)。既然我們能與遠(yuǎn)程倉庫同步,那么就可以分享任何能被 Git 管理的更新.
git fetch
git fetch 做了些什么呢?
- 從遠(yuǎn)程倉庫下載本地倉庫中缺失的提交記錄
- 更新遠(yuǎn)程分支指針
實(shí)際上將本地倉庫中的遠(yuǎn)程分支更新成了遠(yuǎn)程倉庫相應(yīng)分支的最新狀態(tài)。遠(yuǎn)程分支反映了遠(yuǎn)程倉庫在你最后一次與它通信時的狀態(tài),git fetch 就是你與遠(yuǎn)程倉庫通信的方式。
git fetch 并不會改變你本地倉庫的狀態(tài)。它不會更新你的 master 分支,也不會修改你磁盤上的文件。
git fetch 的理解為單純的下載操作。
git pull
當(dāng)遠(yuǎn)程分支中有新的提交時,你可以像合并本地分支那樣來合并遠(yuǎn)程分支:
git cherry-pick origin/master git rebase origin/master git merge origin/master實(shí)際上,由于先抓取更新再合并到本地分支這個流程很常用,因此 Git 提供了一個專門的命令來完成這兩個操作。它就是 git pull
下圖的左側(cè)是遠(yuǎn)程倉庫。
我們通過命令:
先下載C3,然后通過merge合并了這一個提交記錄,這樣我們的master分支就包含了遠(yuǎn)程倉庫中的更新。
git pull 其實(shí)就是git fetch和git merge <just-fetched-branch> 的縮寫
git push
git push 與 git pull 相反,負(fù)責(zé)將你的變更上傳到指定的遠(yuǎn)程倉庫,并在遠(yuǎn)程倉庫上合并你的新提交記錄。一旦 git push 完成, 你的朋友們就可以從這個遠(yuǎn)程倉庫下載你分享的成果。
偏離的提交歷史,十分重要!!!
假設(shè)你周一克隆了一個倉庫,然后開始研發(fā)某個新功能。到周五時,你新功能開發(fā)測試完畢,可以發(fā)布了。但是 —— 天啊!你的同事這周寫了一堆代碼,還改了許多你的功能中使用的 API,這些變動會導(dǎo)致你新開發(fā)的功能變得不可用。但是他們已經(jīng)將那些提交推送到遠(yuǎn)程倉庫了,因此你的工作就變成了基于項(xiàng)目舊版的代碼,與遠(yuǎn)程倉庫最新的代碼不匹配了。
此時git是不允許你push變更的,它會強(qiáng)制你先合并并遠(yuǎn)程最新的代碼,然后才能分享你的工作。
最直接的方法就是通過 rebase 調(diào)整你的工作
如果我們在push之前做rebase的話
| 圖1 | 圖2 |
git fetch 更新了本地倉庫中的遠(yuǎn)程分支,然后用rebase將我們的工作移動到最新的提交記錄下面,最后在git push推送到遠(yuǎn)程倉庫。
也可以精簡指令為:
我們還可以使用merge
盡管git merge不會移動工作(它會創(chuàng)建新的合并提交),但是它會告訴git 你已經(jīng)合并了遠(yuǎn)程倉庫的所有變更。這是因?yàn)檫h(yuǎn)程分支現(xiàn)在是你本地分支的祖先,也就是說你的提交已經(jīng)包含了遠(yuǎn)程分支的所有變化。
我們用 git fetch 更新了本地倉庫中的遠(yuǎn)程分支,
然后合并了新變更到我們的本地分支(為了包含遠(yuǎn)程倉庫的變更),
最后我們用 git push 把工作推送到遠(yuǎn)程倉庫
| 圖1 | 圖2 |
配置參數(shù)選項(xiàng)
全局配置
# 用戶信息 git config --global user.name "your_name" git config --gloabl user.email "your_email"# 文本編輯器 git config --global core.editor "nvim" # 分頁器 分頁器作用詳見 https://blog.csdn.net/chuandao4139/article/details/100814046 git config --global core.pager "more"# 別名 git config --gloabl alias.gs "git status"# 糾錯 git config --global help.autocorrect 1個人配置
# 不加 --global 參數(shù)的話,則為個人配置 git config --list git config user.name git config user.name "your_name"# 如果在項(xiàng)目中設(shè)置,則保存在 .git/config 文件里面 cat .git/config [user]name = "your_name" ......merge 與 rebase的選擇
只對尚未推送或分享給他人的本地修改執(zhí)行rebase操作操作清理歷史。
從不對已經(jīng)推送到倉庫的提交記錄執(zhí)行rebase操作。
更新倉庫提交歷史
合并多個commit提交記錄
當(dāng)為了完成一個功能提交多個commit記錄,在提交PR之前,需要整理這些提交記錄。包括合并、刪除等操作
# 調(diào)整最近五次的提交記錄 git rebase -i HEAD~5 git rebase -i xxxxx # 往前第六次的commit版本號 reword xxxx3 3rd commit squash xxxx4 4th commit pick xxxx5 5th commit fixup xxxx6 6th commit drop xxxx7 7th commit# 查看提交歷史記錄 git log * ce813eb - (HEAD -> master) 5th commit * aa2f043 - 3rd commit -> modified * 6c5418f - 2nd commit * c8f7dea - 1st commit對于各個參數(shù)的解釋:
| 1 | p/pick | 使用這個記錄 |
| 2 | r/reword | 使用這個記錄,并且修改提交信息 |
| 3 | e/edit | 使用這個記錄,rebase時會暫停允許你修改這個commit |
| 4 | s/squash | 使用這個記錄,將當(dāng)前commit與上一個commit合并 |
| 5 | f/fixup | 與squash相同,但是不會保存當(dāng)前commit的提交信息 |
| 6 | x/exec | 執(zhí)行其他shell命令 |
| 7 | d/drop | 移除這個commit記錄 |
刪除意外調(diào)試的測試代碼
有時提交之后,我們才發(fā)現(xiàn)提交的歷史記錄中存在這一些問題,但是此時又不希望新生成一個commit記錄。此時可以修改之前的commit提交記錄。
git add filename # 更改當(dāng)前最新一次提交記錄 git commit --amend # 改變且不改變提交信息 git commit --amend --no-edit # 如果想改變提交最新一次提交記錄并修改信息 git commit --amend -m "memo"如何處理工作中斷
現(xiàn)在我們正在一個分支上為項(xiàng)目添加一個小功能,此時,線上環(huán)境的有一個bug需要讓我們修復(fù),但是我們添加的小功能并沒有完成。
如果此時,我們直接切換到主干分支,會將之前分支沒有來得及提交的內(nèi)容全部都帶到了主干分支上,這是我們不想看到的情況。
此時我們需要保存上個分支的工作狀態(tài),在我們修改完成線上bug之后,再繼續(xù)工作。
git中可以使用stash子命令幫助我們當(dāng)前工作區(qū)、暫存區(qū)當(dāng)中修改都保存到堆棧之中。等我們需要處理的時候,再彈出堆棧中的內(nèi)容,我們再次開發(fā)
# 存儲當(dāng)前的修改但不提交 git stash # 保存當(dāng)前狀態(tài) 包括 untracked的文件 git stash -u # 展示所有 stashes 信息 git stash list # 回到某個 stash 狀態(tài) git stash apply <stash@{n}> # 刪除儲藏區(qū) git stash drop <stash@{n}> # 回到最后一個 stash 的狀態(tài)并刪除這個 stash 信息 git stash pop # 刪除所有的 stash 信息 git stash clear # 從 stash 中拿出某個文件的修改 git checkout <stash@{n}> -- <file-path>比較保險(xiǎn)的做法是將當(dāng)前所有修改進(jìn)行push并保存到遠(yuǎn)程倉庫中,這樣不要害怕本地文件丟失的問題。等到我們需要繼續(xù)開發(fā)的時候,拉下對應(yīng)內(nèi)容,再想辦法進(jìn)行補(bǔ)救。
# 將工作區(qū)和暫存區(qū)覆蓋最近一次提交 git commit --amend git commit --amend -m "memo"# 會退到指定版本并記錄修改內(nèi)容(--mixed) # 本地倉庫覆蓋到工作區(qū)(保存回退文件內(nèi)容修改) git reset xxxx(某個版本號) git reset HEAD~ 退回到上一個版本 git reset HEAD~2 退回到上兩個版本 # 本地倉庫覆蓋到工作區(qū)(不保留修改直接刪除掉) git reset --soft <commit/reference> # 本地倉庫覆蓋到工作區(qū)(保留修改并加到暫存區(qū)) git reset --hard <commit/reference>總結(jié)
- 上一篇: raft算法学习(一):角色概念以及选举
- 下一篇: gcc 编译器使用指南