git基本操作
git add
添加文件到暫存區(qū)
# 添加某個(gè)文件到暫存區(qū)阳谍,后面可以跟多個(gè)文件,以空格區(qū)分
git add xxx
# 添加當(dāng)前更改的所有文件到暫存區(qū)迂猴。
git add .
復(fù)制代碼
git commit
# 提交暫存的更改扁凛,會(huì)新開編輯器進(jìn)行編輯
git commit
# 提交暫存的更改盾沫,并記錄下備注
git commit -m "you message"
# 等同于 git add . && git commit -m
git commit -am
# 對(duì)最近一次的提交的信息進(jìn)行修改,此操作會(huì)修改commit的hash值
git commit --amend
復(fù)制代碼
git pull
pull =fetch+merge
# 從遠(yuǎn)程倉(cāng)庫(kù)拉取代碼并合并到本地,可簡(jiǎn)寫為 git pull 等同于 git fetch && git merge
git pull <遠(yuǎn)程主機(jī)名> <遠(yuǎn)程分支名>:<本地分支名>
# 使用rebase的模式進(jìn)行合并
git pull --rebase <遠(yuǎn)程主機(jī)名> <遠(yuǎn)程分支名>:<本地分支名>
復(fù)制代碼
git fetch
與 git pull
不同的是 git fetch
操作僅僅只會(huì)拉取遠(yuǎn)程的更改殿漠,不會(huì)自動(dòng)進(jìn)行 merge 操作赴精。對(duì)你當(dāng)前的代碼沒有影響
# 獲取遠(yuǎn)程倉(cāng)庫(kù)特定分支的更新
git fetch <遠(yuǎn)程主機(jī)名> <分支名>
# 獲取遠(yuǎn)程倉(cāng)庫(kù)所有分支的更新
git fetch --all
復(fù)制代碼
git branch
# 新建本地分支,但不切換
git branch <branch-name>
# 查看本地分支
git branch
# 查看遠(yuǎn)程分支
git branch -r
# 查看本地和遠(yuǎn)程分支
git branch -a
# 刪除本地分支
git branch -D <branch-nane>
# 重新命名分支
git branch -m <old-branch-name> <new-branch-name>
Workspace:工作區(qū)绞幌,就是平時(shí)進(jìn)行開發(fā)改動(dòng)的地方蕾哟,是當(dāng)前看到最新的內(nèi)容,在開發(fā)的過程也就是對(duì)工作區(qū)的操作
Index:暫存區(qū)莲蜘,當(dāng)執(zhí)行 git add
的命令后谭确,工作區(qū)的文件就會(huì)被移入暫存區(qū),暫存區(qū)標(biāo)記了當(dāng)前工作區(qū)中那些內(nèi)容是被 Git 管理的票渠,當(dāng)完成某個(gè)需求或者功能后需要提交代碼逐哈,第一步就是通過 git add
先提交到暫存區(qū)。
Repository:本地倉(cāng)庫(kù)问顷,位于自己的電腦上昂秃,通過 git commit
提交暫存區(qū)的內(nèi)容,會(huì)進(jìn)入本地倉(cāng)庫(kù)杜窄。
Remote:遠(yuǎn)程倉(cāng)庫(kù)肠骆,用來托管代碼的服務(wù)器,遠(yuǎn)程倉(cāng)庫(kù)的內(nèi)容能夠被分布在多個(gè)地點(diǎn)的處于協(xié)作關(guān)系的本地倉(cāng)庫(kù)修改塞耕,本地倉(cāng)庫(kù)修改完代碼后通過 git push
命令同步代碼到遠(yuǎn)程倉(cāng)庫(kù)蚀腿。
簡(jiǎn)單案例
-
首先建立一個(gè)文件夾作為倉(cāng)庫(kù)
mkdir ~workspace/git_repos
-
進(jìn)入倉(cāng)庫(kù),初始化文件夾荷科,讓它成為倉(cāng)庫(kù)唯咬。任何目錄都可通過git init初始化為倉(cāng)庫(kù),不限數(shù)量畏浆。
~/workspace/git_repos ? git init 提示:使用 'master' 作為初始分支的名稱胆胰。這個(gè)默認(rèn)分支名稱可能會(huì)更改。要在新倉(cāng)庫(kù)中 提示:配置使用初始分支名刻获,并消除這條警告蜀涨,請(qǐng)執(zhí)行: 提示: 提示: git config --global init.defaultBranch <名稱> 提示: 提示:除了 'master' 之外,通常選定的名字有 'main'蝎毡、'trunk' 和 'development'厚柳。 提示:可以通過以下命令重命名剛創(chuàng)建的分支: 提示: 提示: git branch -m <name> 已初始化空的 Git 倉(cāng)庫(kù)于 /Users/pang/workspace/git_repos/.git/
-
創(chuàng)建測(cè)試文件README.md,通過git add命令把它放入暫存區(qū)
# 或者使用git add . 這兩個(gè)命令都是把本地文件加載到暫存區(qū)沐兵,讓git知道我們需要跟蹤此文件的變動(dòng) ~/workspace/git_repos(master*) ? git add -A # 通過git status 可以查看狀態(tài)别垮,如果變?yōu)榫G色則說明已經(jīng)加載到暫存區(qū) ~/workspace/git_repos(master*) ? git status 位于分支 master 尚無提交 要提交的變更: (使用 "git rm --cached <文件>..." 以取消暫存) 新文件: README.md
-
github或者gitee創(chuàng)建遠(yuǎn)程倉(cāng)庫(kù)
具體參考github~/workspace/git_repos(master*) ? git remote add origin https://github.com/xxxx/git_repos.git # origin為遠(yuǎn)端倉(cāng)庫(kù)名字,約定俗成的最好別改 # -u 參數(shù)意思是以后就直接git push就行了 不需要特意加遠(yuǎn)端倉(cāng)庫(kù)名字 ~/workspace/git_repos(master*) ? git push origin master -u Username for 'https://github.com': xxxx Password for 'https://xxxx@github.com': 枚舉對(duì)象中: 4, 完成. 對(duì)象計(jì)數(shù)中: 100% (4/4), 完成. 使用 8 個(gè)線程進(jìn)行壓縮 壓縮對(duì)象中: 100% (3/3), 完成. 寫入對(duì)象中: 100% (4/4), 437 字節(jié) | 437.00 KiB/s, 完成. 總共 4(差異 0)扎谎,復(fù)用 0(差異 0)碳想,包復(fù)用 0 To https://github.com/xxxx/git_repos.git * [new branch] master -> master 分支 'master' 設(shè)置為跟蹤來自 'origin' 的遠(yuǎn)程分支 'master'烧董。
-
克隆遠(yuǎn)程倉(cāng)庫(kù)
# 后面跟新的目錄名 ~/workspace/git_repos(master) ? git clone https://github.com/xxxx/git_repos.git demo 正克隆到 'demo'... remote: Enumerating objects: 7, done. remote: Counting objects: 100% (7/7), done. remote: Compressing objects: 100% (5/5), done. remote: Total 7 (delta 0), reused 7 (delta 0), pack-reused 0 接收對(duì)象中: 100% (7/7), 完成.
-
進(jìn)入demo目錄,修改克隆文件作為測(cè)試
~/workspace/git_repos(master*) ? cd demo ~/workspace/git_repos/demo(master) ? vim README.md # vim README.md # 修改一次看看 #添加暫存區(qū) ~/workspace/git_repos/demo(master*) ? git add README.md # 提交修改 ~/workspace/git_repos/demo(master*) ? git commit -m "second modify README.md" [master 6541538] second modify README.md 1 file changed, 1 insertion(+), 1 deletion(-) # push到遠(yuǎn)程倉(cāng)庫(kù) ~/workspace/git_repos/demo(master) ? git push README.md
-
回到上一層目錄胧奔,此時(shí)發(fā)現(xiàn)遠(yuǎn)程倉(cāng)庫(kù)為新的逊移,本地倉(cāng)庫(kù)為舊的,這是使用git pull 拉取遠(yuǎn)程倉(cāng)庫(kù)
~/workspace/git_repos/demo(master) ? cd ../ ~/workspace/git_repos(master*) ? git pull remote: Enumerating objects: 5, done. remote: Counting objects: 100% (5/5), done. remote: Compressing objects: 100% (2/2), done. remote: Total 3 (delta 0), reused 3 (delta 0), pack-reused 0 展開對(duì)象中: 100% (3/3), 286 字節(jié) | 143.00 KiB/s, 完成. 來自 https://github.com/xxxx/git_repos 34dd439..6541538 master -> origin/master 更新 34dd439..6541538 Fast-forward README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) # 發(fā)現(xiàn)已經(jīng)拉取到最新的文件到本地 ~/workspace/git_repos(master*) ? cat README.md 修改一次看看
git的分支
head表示最后一次提交的指針
簡(jiǎn)單案例
# git branch xxx 創(chuàng)建分支
~/workspace/git_repos(master*) ? git branch feature1
# git branch 查看分支列表
~/workspace/git_repos(master*) ? git branch
# git checkout xxx 切換分支
~/workspace/git_repos(master*) ? git checkout feature1
切換到分支 'feature1'
# 在feature1下創(chuàng)建文件龙填,提交暫存區(qū)胳泉,提交本地倉(cāng)庫(kù)
~/workspace/git_repos(feature1*) ? touch test.txt
~/workspace/git_repos(feature1*) ? git add test.txt
~/workspace/git_repos(feature1*) ? git commit -m "add test.txt"
[feature1 8989c72] add test.txt
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 test.txt
# 創(chuàng)建分支feature2
~/workspace/git_repos(feature1*) ? git branch feature2
#切換分支feature2
~/workspace/git_repos(feature1*) ? git checkout feature2
切換到分支 'feature2'
#由于在feature1下創(chuàng)建的feature2所以feature2可以產(chǎn)看到feature1下的文件
~/workspace/git_repos(feature2*) ? cat test.txt
#git checkout -b xxxx 創(chuàng)建并切換分支xxxx
~/workspace/git_repos(feature2*) ? git checkout -b feature3
切換到一個(gè)新分支 'feature3'
# git branch -d xxx 刪除分支xxx
~/workspace/git_repos(feature3*) ? git branch -d feature2
已刪除分支 feature2(曾為 8989c72)。
# 在feature3下創(chuàng)建文件岩遗,提交暫存區(qū)扇商,提交本地倉(cāng)庫(kù)
~/workspace/git_repos(feature3*) ? vim test2.txt
~/workspace/git_repos(feature3*) ? git add test2.txt
~/workspace/git_repos(feature3*) ? git commit -m "add test2.txt"
[feature3 f47ec0f] add test2.txt
1 file changed, 1 insertion(+)
create mode 100644 test2.txt
# 切換到master分支
~/workspace/git_repos(feature3*) ? git checkout master
切換到分支 'master'
您的分支與上游分支 'origin/master' 一致。
# 刪除feature3喘先,發(fā)現(xiàn)無法直接刪除钳吟,因?yàn)閙aster和feature3沒有合并廷粒。
# git branch -D xxx 強(qiáng)制刪除
~/workspace/git_repos(master*) ? git branch -d feature3
error: 分支 'feature3' 沒有完全合并窘拯。
如果您確認(rèn)要?jiǎng)h除它,執(zhí)行 'git branch -D feature3'坝茎。
# 合并feature3
~/workspace/git_repos(master*) ? git merge feature3
更新 6541538..f47ec0f
Fast-forward
test.txt | 0
test2.txt | 1 +
2 files changed, 1 insertion(+)
create mode 100644 test.txt
create mode 100644 test2.txt
#提交到遠(yuǎn)程倉(cāng)庫(kù)
#但此時(shí)遠(yuǎn)程倉(cāng)庫(kù)的分支列表除了master分支以外沒有其他分支
~/workspace/git_repos(master*) ? git push
枚舉對(duì)象中: 7, 完成.
對(duì)象計(jì)數(shù)中: 100% (7/7), 完成.
使用 8 個(gè)線程進(jìn)行壓縮
壓縮對(duì)象中: 100% (4/4), 完成.
寫入對(duì)象中: 100% (6/6), 516 字節(jié) | 516.00 KiB/s, 完成.
總共 6(差異 1)涤姊,復(fù)用 0(差異 0),包復(fù)用 0
remote: Resolving deltas: 100% (1/1), done.
To https://github.com/xxxx/git_repos.git
6541538..f47ec0f master -> master
#切換到feature1
~/workspace/git_repos(master*) ? git checkout feature1
切換到分支 'feature1'
#git push “遠(yuǎn)程倉(cāng)庫(kù)名” “分支名”
#這樣提交的話遠(yuǎn)程倉(cāng)庫(kù)就要新分支feature1了
~/workspace/git_repos(feature1*) ? git push origin feature1
總共 0(差異 0)嗤放,復(fù)用 0(差異 0)思喊,包復(fù)用 0
remote:
remote: Create a pull request for 'feature1' on GitHub by visiting:
remote: https://github.com/xxxx/git_repos/pull/new/feature1
remote:
To https://github.com/xxxx/git_repos.git
* [new branch] feature1 -> feature1
# git push origin :feature1 刪除分支
~/workspace/git_repos(feature1*) ? git push origin :feature1
To https://github.com/xxxx/git_repos.git
- [deleted] feature1
# git push origin feature1:f1 遠(yuǎn)程倉(cāng)庫(kù)添加以f1的命名新分支
~/workspace/git_repos(feature1*) ? git push origin feature1:f1
總共 0(差異 0),復(fù)用 0(差異 0)次酌,包復(fù)用 0
remote:
remote: Create a pull request for 'f1' on GitHub by visiting:
remote: https://github.com/xxxx/git_repos/pull/new/f1
remote:
To https://github.com/xxxx/git_repos.git
* [new branch] feature1 -> f1
git rebase
他的作用和 merge 很相似恨课,用于把一個(gè)分支的修改合并到當(dāng)前分支上。如下圖所示岳服,下圖介紹了經(jīng)過 rebase 后提交歷史的變化情況剂公。
例子:
假設(shè)我們現(xiàn)在有2條分支,一個(gè)為 master吊宋,一個(gè)為 feature/1纲辽,他們都基于初始的一個(gè)提交 add readme 進(jìn)行檢出分支,之后璃搜,master 分支增加了 3.js 和 4.js 的文件拖吼,分別進(jìn)行了2次提交,feature/1 也增加了 1.js 和 2.js 的文件这吻,分別對(duì)應(yīng)以下2條提交記錄吊档。
此時(shí),切換到 feature/1 分支下唾糯,執(zhí)行 git rebase master
怠硼,成功之后涡上,通過 git log
查看記錄。
如下圖所示:可以看到先是逐個(gè)應(yīng)用了 mater 分支的更改拒名,然后以 master 分支最后的提交作為基點(diǎn)吩愧,再逐個(gè)應(yīng)用 feature/1 的每個(gè)更改。
merge和rebase區(qū)別
不同于 git rebase
的是增显,git merge
在不是 fast-forward(快速合并)的情況下雁佳,會(huì)產(chǎn)生一條額外的合并記錄,類似 Merge branch 'xxx' into 'xxx'
的一條提交信息同云。
回滾操作
git reset
git reset master^ # ^代表回退一個(gè)版本糖权,回退兩個(gè)版本就^^,以此類推
git reset master~3 # 一次性回退三個(gè)版本
git reset --option 版本號(hào)
--mixed:會(huì)把暫存區(qū)的文件丟棄炸站,不會(huì)動(dòng)工作目錄里的文件
--soft:工作目錄和暫存區(qū)的文件都不會(huì)丟棄
--hard:工作目錄和暫存區(qū)的文件全部丟棄
git revert
撤銷某次操作星澳,此次操作之前之后的commit和history都會(huì)保留,并且把這次撤銷作為一次最新的提交
下面就用一個(gè)案例來理解一下這個(gè)命令旱易,如下圖所示禁偎,假設(shè)被紅框框起來的地方是會(huì)引起 bug 的一次提交,在他的提交之后阀坏,又進(jìn)行了2次提交如暖,其中包含了其它同事的提交。
此時(shí)想把引起提交的 bug 的干掉忌堂,執(zhí)行 git revert 1121932
盒至,執(zhí)行操作后,再打開查看日志士修,如下圖所示枷遂,可以看到是新增了一條 commit 記錄,這個(gè) commit 的產(chǎn)生的 msg 是自動(dòng)生成的棋嘲,Revert 開頭酒唉,后面跟撤回的 commit-msg 信息 之前的 commit 記錄并沒有消失,此時(shí)也達(dá)到了代碼回退的效果