我寫的這篇文章,主要是記錄自己的學習程序,也希望幫助讀者少踩坑(比如不同版本可能命令不兼容等),本文面向git零基礎初學者,建議讀者按照文中命令自己全部操作一遍(注意運行環境),
我的運行環境:win10 + VMware + ubuntu 18.04 + git 2.33.0(所有命令均在root用戶下執行)
本文參考資料:
[1] 廖雪峰 Git教程
[2] 博客園 一個小時學會Git
[3] Git中文官方檔案
資料在精不在多,以上3個資料足以詳細解釋git的各項命令,建議把這些資料都看一下,從時效性來說,[1]和[2]中的有些命令是老版本的,而[3]的官方檔案能看到最新的命令使用方法;從趣味性和易懂性來說,則[1]和[2]更容易讓人理解和掌握,當然,本文綜合了時效性和易懂性,保證使用新版本的命令,并盡量清楚地表述各個命令的作用,
未經允許,本文禁止轉載! 作者:nefu_ljw(CSDN/博客園同號) (本文所有參考資料均在對應位置標明,如有侵權,請聯系我洗掉)
目錄- 0. Git 安裝 & 更新
- 1. 基本概念:作業區、暫存區、版本庫、遠程倉庫
- 2. Git檔案操作
- 2.1 創建倉庫(git init)
- 2.2 提交變更(git add, git commit)
- 2.3 管理變更(git add/rm, git restore)
- 2.4 版本回退(git reset)
- 2.5 查看命令(git status, git log, git reflog, git diff)
- 2.6 小結:提交變更 + 管理變更
- 3. 分支管理
- 3.1 查看/創建/切換/洗掉分支(git branch, git switch)
- 3.2 合并分支(git merge)
- 3.3 bug分支(git stash, git cherry-pick)
- 4. 遠程倉庫
- 4.1 配置git
- 4.2 克隆遠程倉庫(git clone)
- 4.3 添加/洗掉遠程倉庫(git remote add/rm)
- 4.4 推送遠程倉庫(git push)
- 4.5 抓取/拉取遠程倉庫(git fetch, git pull)
- 4.6 查看遠程倉庫(git remote -v/show)
- 4.7 查看/跟蹤/洗掉 本地分支與遠程分支(git branch -a/-vv/--track/--set-upstream-to/-dr, git push origin --delete)
- 4.8 多人協作(push被拒絕、pull自動合并失敗、解決沖突)
- 其他操作
- 配置別名(偷懶神器)
- 附贈資料
0. Git 安裝 & 更新
安裝git,
apt install git
查看git版本,
git --version
若版本低于2.23,請更新git,(git 2.23版本新增了switch、restore命令,后文會用到)
add-apt-repository ppa:git-core/ppa #adding a Launchpad PPA(Personal Package Archive) repository
apt update
apt install git
1. 基本概念:作業區、暫存區、版本庫、遠程倉庫
- 作業區(Workspace):本地存放檔案的地方,Git會知道這里的檔案變更,如添加/修改/洗掉檔案,
- 暫存區(Stage/Index):臨時存放檔案變更資訊,事實上它是一個名為
index的檔案, - 版本庫(Repository):作業區有一個隱藏目錄
.git,它是Git的版本庫,為了與遠程倉庫區分,將其明確稱為本地版本庫(Local Repository),其中有一個HEAD指向當前版本庫版本, - 遠程倉庫(Remote Directory):托管代碼的服務器,可以簡單的認為是你專案組中的一臺電腦用于遠程資料交換,
參考: 一個小時學會Git - 作業區域
Directory:使用Git管理的一個目錄,也就是一個倉庫,包含我們的作業空間和Git的管理空間,
Workspace:需要通過Git進行版本控制的目錄和檔案,這些目錄和檔案組成了作業空間,
.git:存放Git管理資訊的目錄,初始化倉庫的時候自動創建,
Index/Stage:暫存區,或者叫待提交更新區,在提交進入repo之前,我們可以把所有的更新放在暫存區,
Local Repo:本地倉庫,一個存放在本地的版本庫;HEAD只指向當前的開發分支(branch),
Stash:隱藏,是一個作業狀態保存堆疊,用于保存/恢復Workspace中的臨時狀態,
2. Git檔案操作
在本章,介紹操作git本地倉庫的一些常用命令,
2.1 創建倉庫(git init)
創建本地倉庫的方法有兩種:一種是本地創建全新倉庫,另一種是克隆遠程倉庫(請見第4章),
本地創建全新倉庫,初始化一個版本庫:
git init
2.2 提交變更(git add, git commit)
下面介紹提交變更到本地版本庫的基本流程,
準備作業:先新建一個目錄learngit,并創建README.md檔案,隨便寫入一句話,
mkdir learngit
cd learngit
touch README.md
echo "# Hello, git!" >> README.md
添加檔案變更到版本庫,分兩步:
- 使用命令
git add <file>,可多次使用,添加多個檔案, - 使用命令
git commit -m <message>,檔案從暫存區提交到版本庫;<message>表示提交的資訊,
git init #初始化一個git的本地倉庫
git add README.md #將作業區README.md檔案的變更移動到暫存區
git commit -m "add README.md" #將暫存區提交到本地倉庫
2.3 管理變更(git add/rm, git restore)
理解:Git跟蹤并管理的是變更,而不是檔案,
-
撤銷作業區變更(撤銷對作業區檔案的添加/修改/洗掉):
git restore <filename>或git checkout -- <filename>, -
撤銷暫存區變更(撤銷git add/rm):
git restore --staged <filename>或git reset HEAD <filename>,
2.23版本的git,考慮到reset, checkout存在多種用法對新手來說不易學習,故引入新命令git restore方便操作,
示例:變更作業區檔案后(比如修改/洗掉檔案),使用git restore撤銷作業區/暫存區的變更,
echo "after git add" >> README.md #在作業區修改README.md,用git status可以看到被修改,但這一變更未加到暫存區
git add README.md #變更被加到暫存區
git restore --staged README.md #撤銷暫存區的變更(README.md的修改),注意,此時作業區檔案還是沒有變
git restore README.md #撤銷作業區的變更,即作業區README.md檔案被還原成修改前
git rm README.md #在作業區洗掉README.md,并且這一變更被加到暫存區
git restore --staged README.md #撤銷暫存區的變更(README.md的洗掉),注意,此時作業區檔案還是沒有變
git restore README.md #撤銷作業區的變更,即作業區README.md檔案被還原成洗掉前
git rm README.md等價于以下兩句:
rm README.md #在作業區中洗掉README.md,但這一變更沒有被加到暫存區
git add README.md #將對README.md的變更加到暫存區
2.4 版本回退(git reset)
Git允許我們在版本的歷史之間穿梭,實際上就是移動HEAD指向的位置(HEAD指向的版本就是當前版本),
用git log可以查看提交歷史,即歷史每次提交的<commit_id>,以便確定要回退到哪個版本,
用git reflog可以查看命令歷史,即所有分支的所有操作記錄(包括commit, reset, checkout, merge等操作),
指定版本到<commit_id>:
git reset --hard <commit_id> #當前分支和HEAD均指向<commit_id>
回退到當前HEAD的上一個commit,撤銷暫存區變更(撤銷commit和add):
git reset --hard HEAD~1 #HEAD~1表示上一個commit版本,如果是往上兩個版本就是HEAD~2;當前版本就是HEAD
回退到當前HEAD的上一個commit,不撤銷暫存區變更(撤銷commit):
git reset --soft HEAD~1
2.5 查看命令(git status, git log, git reflog, git diff)
git status查看git倉庫中,作業區、暫存區、版本庫的當前狀態,git log查看提交歷史,可加選項:--oneline每行顯示一個commit,例如顯示9af21bf add README.md,那么<commit_id>前幾個字符就是9af21bf,--all顯示所有分支的提交歷史,否則只顯示當前分支的提交歷史,--graph顯示分支合并,以橫線形式連接曾有過合并的各個提交,
git reflog查看命令歷史,git diff查看作業區和暫存區差異,git diff --cached查看暫存區和版本庫差異,git diff -- HEAD~1查看作業區和版本庫的差異,HEAD~1可以改成HEAD、HEAD~2等等,git diff HEAD HEAD~1查看版本庫HEAD與版本庫HEAD~1之間的差異(最新的commit和上一次commit),
2.6 小結:提交變更 + 管理變更
- 作業區變更:任意的添加/修改/洗掉檔案,
- 撤銷作業區變更:
git restore <filename>或git checkout -- <filename>,
- 撤銷作業區變更:
git add作業區→暫存區添加檔案變更,- 撤銷add:
git restore --staged <filename>或git reset HEAD <filename>,
- 撤銷add:
git commit暫存區→版本庫提交檔案變更,- 撤銷commit:
git reset --soft <commit_id>, - 撤銷commit和add:
git reset --hard <commit_id>,
- 撤銷commit:
本地倉庫的各項管理命令可以參照下圖方便記憶(從右往左看):

3. 分支管理
本章介紹git的本地分支管理,(實際上,既有本地分支,也有遠程分支,具體請見4.8章)
提醒:對于想快速上手的初學者,比如你只想推送本地倉庫到遠程倉庫,那么可暫時跳過本章,直接去看第4章遠程倉庫,
3.1 查看/創建/切換/洗掉分支(git branch, git switch)
查看本地分支:
git branch #要查看遠程分支則加上選項-r,查看所有分支則加上選項-a
創建分支:
git branch <name>
切換分支:
git switch <name> #等價于git checkout <name> (注意:switch命令是git 2.23版本的新命令)
創建+切換分支:
git switch -c <name> #等價于git checkout -b <name>
洗掉普通分支:
git branch -d <name>
強制洗掉未合并的分支:
git branch -D <name>
3.2 合并分支(git merge)
- 快速合并(Fast-forward):合并當前分支(舊)到某分支(新)的位置,
git merge <name> #某分支名為<name>
- 非快速合并:合并當前分支+某分支,產生一個新的提交,合并到這個新提交的位置,這樣可以保存之前的分支歷史,
git merge --no-ff -m <message> #<message>表示新提交的資訊
操作示例:
首先創建并切換到分支feature,并在feature分支上進行一次提交,
# 首先用git status看看是否位于分支master(如果不是就用git switch master先切換一下)
git switch -c feature #創建并切換到分支feature
echo "add merge" >> README.md #修改README.md
git add README.md
git commit -m "add merge" #提交
則此時狀態如下圖(藍線表示master分支,紅線表示feature分支):

然后,用git switch master切換回master分支,此后,HEAD指向master,
接下來請任選(1)或(2)的命令全部執行一遍,即選擇你的合并策略(Fast-forward 或 no-fast-forward),
(1)快速合并
git merge feature
用git log --oneline --graph顯示歷史提交資訊如下:
* f7a06a2 (HEAD -> master, feature) add merge
* e0e4ca3 conflict fixed (注:這里是你上一次的提交資訊,與合并無關)
合并后的狀態如下圖:

(2)非快速合并
git merge feature --no-ff -m "merge with no-ff"
用git log --oneline --graph顯示歷史提交資訊如下:
* fc7e0ee (HEAD -> master) merge with no-ff
|\
| * d4d0ec9 (feature) add merge
|/
* e0e4ca3 conflict fixed (注:這里是你上一次的提交資訊,與合并無關)
合并后的狀態如下圖:

(選做)最后,可以用git branch -d feature洗掉feature分支,
(3)兩種合并策略的區別

3.3 bug分支(git stash, git cherry-pick)
假設現在有master, feature分支,你在feature分支上進行作業,寫一個hello.py檔案,并將其添加到了暫存區,
git switch feature #切換到feature分支,如果沒有這個分支就用git switch -c feature創建并切換
touch hello.py & echo "print('hello')" >> hello.py #創建了一個python代碼檔案并寫入了內容
git add hello.py #將變動加至暫存區
git add之后,用git status可以看到"hello.py的變更處于待提交狀態",
此時,突然發現有一個緊急的bug需要修復,但hello.py還沒有寫完,暫時無法commit,
于是你打算創建一個新的bug分支,但當前分支的作業狀態必須先保存下來,那么可以用:
git stash
git stash可以把當前作業狀態儲存到stash這個堆疊之中,等以后出堆疊,即可還原現場,繼續作業,
當前作業狀態入堆疊后,再用git status可以看到"無檔案要提交,干凈的作業區",
假設要在feature分支上修復bug,那么就在feature分支上創建并切換到bug分支(命名為issue-101),假設修復bug就是修改README.md檔案,修復完就commit,
#現在位于feature分支進行操作,然后創建并切換到bug分支
git switch -c issue-101 #bug分支
echo "Fixed the bug of README.md" >> README.md
git add README.md
git commit -m "fix bug 101"
然后,再切換回feature分支,將bug分支與feature分支進行非快速合并:
git switch feature
git merge issue-101 --no-ff -m "merged bug fix 101"
那么此時,已經完成了bug修復,可以重返當時儲存的作業狀態了:
git stash pop #將堆疊頂的作業狀態出堆疊,同時洗掉堆疊頂內容
到此為止,我們就完成了feature分支上bug的修復程序,總結一下流程:
- feature分支,用
git stash保存作業狀態, - 切換到bug分支,修復完bug,
commit, - 切換回feature分支,將bug分支與feature分支合并,用
git stash pop還原作業狀態,
現在我們已經修復了feature分支上的bug,假設master分支上也要修復相同的bug,怎么辦?
不用那么麻煩的再做一遍修復bug、合并分支的作業,可以用git cherry-pick <commit_id>,它能把bug分支的commit操作直接"復制",然后commit到當前分支:
git switch master
git stash # 如果master分支上有待提交的變更,那么必須先保存狀態
git cherry-pick 8436eb8 #8436eb8是修復bug的<commit_id>,可用git log查看為8436eb8 (issue-101) fix bug 101
git stash pop
(選做)如果你需要保存多個作業狀態,可以多次入堆疊,想恢復某個作業狀態的時候,先用git stash list查看stash內容,再用git stash apply恢復到指定的作業狀態:
git stash list # 查看stash內容
git stash apply stash@{0} #堆疊頂為stash@{0},堆疊頂的下一個為stash@{1}
注意:git stash apply并不會洗掉堆疊內的任何內容,但git stash pop將堆疊頂作業狀態出堆疊的同時也會洗掉堆疊頂的內容,
小結:
-
git stash 暫存當前作業狀態,等恢復現場后繼續作業
-
git stash list 查看所有暫存的作業狀態
-
git stash pop 恢復作業狀態,洗掉堆疊頂內容
-
git stash apply 恢復作業狀態,不洗掉堆疊內內容
-
git stash drop 洗掉堆疊頂內容
4. 遠程倉庫
在本章,你需要有一個GitHub賬號,并且在GitHub上添加了一個遠程倉庫,遠程倉庫是指托管在互聯網的版本庫,
注意:遠程倉庫可以在你的本地主機上, 你完全可以在一個“遠程”倉庫上作業,而實際上它在你本地的主機上,詞語“遠程”未必表示倉庫在互聯網上的其它位置,而只是表示它在別處,為了區分這一概念,后文用遠程倉庫服務器/遠程服務器表示GitHub托管的遠程倉庫,
參考:(官方檔案)2.5 Git 基礎 - 遠程倉庫的使用、(博客)git遠程倉庫分支的各命令的具體決議
4.1 配置git
配置git的所有操作可以參考此文,
設定用戶名和郵箱,
git config --global user.email "[email protected]" # --global表示全域設定
git config --global user.name "your_name"
查看配置,
git config -l
將SSH Key添加到GitHub,
ssh-keygen -t rsa -C "[email protected]" # 結果顯示:Your public key has been saved in /root/.ssh/id_rsa.pub
cat /root/.ssh/id_rsa.pub # 查看公鑰并將其復制,之后粘貼到GitHub網頁上
在GitHub網頁中,點擊個人頭像 → Settings → SSH and GPG keys → New SSH key,添加公鑰,
4.2 克隆遠程倉庫(git clone)
第2章提到,創建本地倉庫的方法之一是克隆遠程倉庫,
git clone <url> #遠程服務器的URL
當你克隆某個遠程倉庫后,默認情況下Git會自動設定本地master分支跟蹤克隆的遠程倉庫的master分支(或其它名字的默認分支),并且默認設定遠程倉庫在本地的別名是origin,
實際上克隆命令是git clone <repo>,表示克隆?個指定repo到本地,其指定repo可以是本地?件系統或者由HTTP或SSH指定的遠程路徑,
4.3 添加/洗掉遠程倉庫(git remote add/rm)
(1)添加遠程倉庫
實際就是給遠程倉庫服務器地址起一個本地的別名/簡稱(習慣命名為origin),
將遠程服務器地址<url> 映射為 本地對遠程服務器的別名<shortname>,命令格式如下:
git remote add <shortname> <url> #將<shortname>與<url>關聯,以后就可以用<shortname>代替<url>
示例:
#進入GitHub遠程倉庫的網頁,點擊Code和SSH,查看SSH協議的<url>,例如[email protected]:nefu-ljw/ACM-Algorithm.git
git remote add origin [email protected]:nefu-ljw/ACM-Algorithm.git
這樣以后,就可以在命令列中使用字串origin代替整個[email protected]:nefu-ljw/ACM-Algorithm.git,
(2)洗掉遠程倉庫
git remote rm <shortname> #洗掉別名<shortname>及其對應的遠程服務器地址
一旦使用這種方式洗掉了一個遠程倉庫,那么所有和這個遠程倉庫相關的遠程跟蹤分支以及配置資訊也會一起被洗掉,
4.4 推送遠程倉庫(git push)
將本地倉庫的分支<branch>推送到遠程服務器<remote>,命令格式如下:
git push <remote> <branch> # 這里的<remote>就是之前添加的遠程服務器地址的別名<shortname>
如果是第一次將本地分支master推送到遠程服務器origin,則使用-u選項指定一個默認服務器:
git push -u origin master #之后會產生遠程分支origin/master,并且本地分支master跟蹤遠程分支origin/master
如果當前分支與多個服務器存在跟蹤關系,可以使用-u選項指定一個默認服務器,以后就可以不加任何引數直接使用git push,
當你和其他人在同一時間克隆,但他們先推送然后你再推送,那么你的推送會被拒絕,因為你要推送的本地分支落后于遠程服務器的分支,你必須先抓取(fetch)他們的作業并將其合并(merge)進你的作業后才能推送,或者用-force選項強行推送你的本地庫,但是這樣會使得遠程服務器丟失其他人的變更,請慎重使用,
注:git push需要輸入用戶名和密碼,輸入密碼時可能出現要求輸入token的問題,可參考此文解決,
4.5 抓取/拉取遠程倉庫(git fetch, git pull)
如果遠程服務器的資料有更新,要將這些新資料下載到本地,可以用git fetch或git pull,
(1)抓取遠程倉庫(fetch)
a. 訪問遠程服務器,從中抓取所有所有分支的更新:
git fetch <remote> #從遠程倉庫服務器<remote>中抓取所有分支的更新
b. 如果只想取回特定分支的更新,可以指定分支名:
git fetch <remote> <branch> #例如git fetch origin master
(2)拉取遠程倉庫(pull,即fetch+merge)
a. 取回遠程服務器<remote>某個分支<remote_branch>的更新,再與本地的指定分支<local_branch>合并:
git pull <remote> <remote_branch>:<local_branch>
示例,取回遠程服務器origin的分支feature,與本地分支master合并:
git pull origin feature:master
b. 如果遠程分支是與本地當前分支合并,則可省略:<local_branch>,如下:
git pull origin feature #等價于先fetch,再merge
這會讓feature在FETCH_HEAD中臨時保留一個副本,并更新遠程跟蹤分支origin/feature,
等價于,先fetch,再merge:
git fetch origin #將遠程服務器origin的所有分支取回到本地,比如遠程分支feature的本地副本為origin/feature
git merge origin/feature #將遠程分支origin/feature合并到當前分支
c. 如果當前分支與遠程分支存在跟蹤關系,則可省略<remote_branch>:<local_branch>,如下:
git pull origin #自動嘗試合并 當前分支跟蹤的遠程分支→當前分支
經常有人在不給任何引數的情況下使用git pull,這一般相當于git pull origin,
(3)抓取(fetch)與拉取(pull)的區別
-
git fetch:獲取遠程服務器的更新到本地,不自動合并到本地分支, -
git pull:獲取遠程服務器的更新到本地,自動合并到本地分支,
4.6 查看遠程倉庫(git remote -v/show)
如果想查看已經配置的遠程倉庫服務器,可以用git remote列出已指定的每一個遠程服務器的簡寫,
你也可以指定選項-v,將會顯示遠程服務器使用的簡寫<shortname>與其對應的<url>,
git remote -v
運行命令后,將會顯示可以進行抓取(fetch)和推送(push)的地址:
origin [email protected]:nefu-ljw/ACM-Algorithm.git (fetch)
origin [email protected]:nefu-ljw/ACM-Algorithm.git (push) (注:如果沒有推送權限,則看不到push的地址)
如果你已經克隆了倉庫,那么至少能看到origin,這是Git給你克隆的遠程服務器的默認別名,
如果想要查看某一遠程倉庫<remote>的更多資訊,可以用:
git remote show <remote>
這個命令列出了當你在特定的分支上執行git push會自動地推送到哪一個遠程分支, 它也同樣地列出了哪些遠程分支不在你的本地,哪些遠程分支已經從服務器上移除了, 還有當你執行git pull時哪些本地分支可以與它跟蹤的遠程分支自動合并,
4.7 查看/跟蹤/洗掉 本地分支與遠程分支(git branch -a/-vv/--track/--set-upstream-to/-dr, git push origin --delete)
(1)查看本地分支和遠程分支:
git branch -a
例如,顯示有本地分支feature、遠程分支origin/feature,則表示你在本地庫中擁有master和origin/master,其中origin/master代表遠程庫中master分支的本地副本,
(2)查看本地分支和遠程分支的跟蹤關系:
git branch -vv
(3)設定跟蹤關系,要使得本地分支feature跟蹤遠程分支origin/feature,有以下方法:
a. git branch(注意:新版本已棄用選項--set-upstream,請使用--track或--set-upstream-to)
- 選項
--track,適合用于還沒有本地分支,它會自動創建一個本地分支并指定它跟蹤指定遠程分支,完整命令如下:
git branch --track feature origin/feature
運行以上命令后,會創建分支feature(HEAD位置不變),并且feature的位置到遠程分支origin/feature,
- 選項
--set-upstream-to,適合用于已有本地分支,它能指定一個已經存在的本地分支跟蹤指定遠程分支,完整命令如下:
#指定本地分支feature跟蹤遠程分支origin/feature
git branch --set-upstream-to=origin/feature feature #指定分支feature可省略,若省略則默認為當前分支
如果先用git switch -c feature創建并切換到分支feature(HEAD位置改變);再運行以上命令,則feature的位置不會到遠程分支origin/feature,
b. git switch
#可以用-c自動從同名的遠程分支創建新分支,并且建立跟蹤;--track是默認選項,可省略
git switch -c feature --track origin/feature
#或:git switch -c feature origin/feature
#或:git checkout -b feature origin/feature
#或:git switch feature
#或:git checkout feature
運行以上命令后,會創建并切換到分支feature(HEAD位置改變),并且feature的位置到遠程分支origin/feature,
(4)洗掉遠程服務器上的遠程分支origin/feature:
git push origin --delete feature #之后可在Github遠程倉庫上看到無feature分支
(5)洗掉本地跟蹤的遠程分支origin/feature:
git branch -dr origin/feature #洗掉本地的遠程分支副本
(6)洗掉本地分支feature:
git branch -d feature
4.8 多人協作(push被拒絕、pull自動合并失敗、解決沖突)
本節對多人協作的操作程序進行示例,事先說明,本節會多次用到查看命令:
- 查看提交歷史和分支情況:
git log --oneline --all - 查看本地分支的跟蹤關系:
git branch -vv
假設已經用git remote add origin [email protected]:nefu-ljw/ACM-Algorithm.git添加了遠程服務器origin,
假設現在有兩臺主機(用兩個作業路徑模擬),A和B,最開始只有A上有本地分支master和遠程分支origin/master,并且它們已經建立了跟蹤關系,
Step 1: 在A上操作(作業路徑/opt/workspace/learngit):
git switch -c feature #之后就會多一個本地分支feature
touch env.txt & echo "env" >> env.txt
git add env.txt
git commit env.txt -m "add env.txt"
git push -u origin feature #之后就會多一個遠程分支origin/feature;加上-u選項,則feature將會跟蹤origin/feature
查看提交歷史和分支情況:
1f776ca (HEAD -> feature, origin/feature) add env.txt
f7a06a2 (origin/master, master) add merge
查看本地分支的跟蹤關系:
* feature 1f776ca [origin/feature] add env.txt
master f7a06a2 [origin/master] add merge
Step 2: 在B上操作(作業路徑/opt/workspace/ACM-Algorithm):
git clone [email protected]:nefu-ljw/ACM-Algorithm.git /opt/workspace/ACM-Algorithm #指定克隆到本地路徑(自選)
cd /opt/workspace/ACM-Algorithm #進入剛才克隆指定的git作業路徑,把它作為B的作業路徑
查看提交歷史和分支情況:
1f776ca (origin/feature) add env.txt
f7a06a2 (HEAD -> master, origin/master, origin/HEAD) add merge
查看本地分支的跟蹤關系:
* master f7a06a2 [origin/master] add merge
可以看到,與A的本地倉庫相比,B少了一個本地分支feature,多了一個遠程分支origin/HEAD,并且當前HEAD指向本地分支master,本地分支master已經跟蹤了遠程分支origin/master,
關于origin/HEAD的解釋:
origin/HEAD表示遠程服務器上的默認分支,即你正在呼叫的遠程庫origin中的HEAD,origin/HEAD是一個本地參考,代表遠程庫中HEAD的本地副本,你在本地倉庫中切換分支時,只是本地HEAD的移動,不會影響origin/HEAD,
參考:Stack Overflow - How does origin/HEAD get set?
origin/HEAD可用git remote set-head origin -d刪掉,也可用git remote set-head origin master設定origin/HEAD指向origin/master,
克隆之后,遠程有origin/feature分支,本地卻沒有feature分支,那么創建和切換到feature分支,并建立跟蹤:
git switch -c feature origin/feature
查看提交歷史和分支情況(成功創建和切換feature分支):
1f776ca (HEAD -> feature, origin/feature) add env.txt
f7a06a2 (origin/master, origin/HEAD, master) add merge
查看本地分支的跟蹤關系(成功建立跟蹤feature→origin/feature):
* feature 1f776ca [origin/feature] add env.txt
master f7a06a2 [origin/master] add merge
在B上繼續操作,修改env.txt,并進行commit和push:
echo "B changed env.txt" >> env.txt
git add env.txt
git commit env.txt -m "B changed env.txt"
git push origin feature #-u可以不寫,因為feature已經跟蹤origin/feature
Step 3: 在A上操作,恰好也修改了env.txt,進行了commit和push,但是A的push在剛才B的push之后:
echo "A changed env.txt" >> env.txt
git add env.txt
git commit env.txt -m "A changed env.txt"
git push origin feature #push被拒絕
然而,push更新被拒絕:
! [rejected] feature -> feature (fetch first)
error: 推送一些參考到 'github.com:nefu-ljw/ACM-Algorithm.git' 失敗
提示:更新被拒絕,因為遠程倉庫包含您本地尚不存在的提交,這通常是因為另外一個倉庫已向該參考進行了推送,再次推送前,您可能需要先整合遠程變更(如 'git pull ...'),詳見 'git push --help' 中的 'Note about fast-forwards' 小節,
那么按照提示,用 'git pull ...' 取得遠程服務器origin的所有更新到本地,并且自動合并origin/feature到當前分支feature:
git pull origin feature #等價于:git fetch origin 且 git merge origin/feature
來自 github.com:nefu-ljw/ACM-Algorithm
* branch feature -> FETCH_HEAD
自動合并 env.txt
沖突(內容):合并沖突于 env.txt
自動合并失敗,修正沖突然后提交修正的結果,
提示我們"合并沖突于env.txt",那查看一下env.txt:
env
<<<<<<< HEAD
A changed env.txt
=======
B changed env.txt
>>>>>>> 435cb9a75b999d9e127cc9cad13a048674dbb6cb
提示我們"自動合并失敗",那么手動解決沖突,修改env.txt為:
env
First, B changed env.txt
Second, A changed env.txt
然后再提交修正的結果,進行add, commit, push即可:
git add env.txt
git commit -m "fixed the conflict of A and B on env.txt"
git push origin feature #這次就push成功了
用git log --oneline --all --graph查看歷史提交和分支合并情況如下:
* 0055c62 (HEAD -> feature, origin/feature) fixed the conflict of A and B on env.txt
|\
| * 435cb9a B changed env.txt
* | 8488b5e A changed env.txt
|/
* 1f776ca add env.txt
* f7a06a2 (origin/master, master) add merge
最后,我們總結一下多人協作的操作程序:
- A創建env.txt,并進行
commit和push, - B克隆A剛才
push的遠程服務器,然后修改了env.txt,并進行commit和push, - A恰好也修改了env.txt,并進行
commit和push,然而push失敗,用pull獲取更新的資料和嘗試自動合并,然而自動合并失敗,需要解決沖突,手動解決沖突后,即可順利進行commit和push,
其他操作
配置別名(偷懶神器)
參考
如果你覺得git log --color --graph --pretty=format:'%Cred%h%Creset -%C(auto)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit這個命令太長了,那么可以將log之后的那一長串配置為別名lg:
git config --global alias.lg "log --color --graph --pretty=format:'%Cred%h%Creset -%C(auto)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit"
之后,你就可以用git lg來直接代替那一長串的命令了!(注意,命令還是要以git開頭的,lg代替的只是后面那一長串)
配置Git的時候,加上--global是針對當前用戶(終端用戶)起作用的,如果不加,那只針對當前的倉庫起作用,
怎么查看組態檔,它們放在哪?
-
查看當前用戶的配置資訊:
git config --global --list,當前用戶的global配置在用戶主目錄下的.gitconfig, -
查看當前倉庫的配置資訊:
git config --local --list,當前倉庫的local配置在倉庫路徑下的.git/config,
每個倉庫的Git組態檔都放在.git/config檔案中,別名就在[alias]后面,要洗掉別名,直接把對應的行刪掉即可,
當前用戶的Git組態檔放在用戶主目錄下的一個隱藏檔案.gitconfig中,配置別名也可以直接修改這個檔案,如果改錯了,可以刪掉檔案重新通過命令配置,
附贈資料
Git Cheat Sheet(常用命令的小冊子):https://liaoxuefeng.gitee.io/resource.liaoxuefeng.com/git/git-cheat-sheet.pdf
標簽(tag)、變基(rebase)這兩章本文就不寫了,大家參考廖雪峰教程即可,
2021.10.24 程式員節快樂!
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/335099.html
標籤:其他
下一篇:陣列模擬(一)

