本教程為小甲魚《極客Python之Git實用教程》課程筆記宁舰,大部分為原課程講義,其中穿插了自己實戰(zhàn)過程中遇到的一些問題及解決辦法。
Git使用教程1---世界上最先進的分布式版本控制系統(tǒng)簡介
Git使用教程2---Git的安裝與理論基礎(chǔ)
Git使用教程3---實戰(zhàn)
Git使用教程4---狀態(tài)
Git使用教程5---回到過去
Git使用教程6---版本對比
Git使用教程7---修改最后一次提交畏浆、刪除文件和重命名文件
Git使用教程8---創(chuàng)建和切換分支
Git使用教程9---合并和刪除分支
Git使用教程10---匿名分支和checkout命令
Git使用教程2---Git的安裝與理論基礎(chǔ)
一鉴扫、Git安裝
windows安裝:進入網(wǎng)站https://git-scm.com/下載安裝,然后在cmd命令行配置
> git config --global user.name "FishC_Service"
> git config --global user.email "fishc_service@126.com"
#檢查信息是否寫入成功
git config --list
ubuntu配置:apt-get install git
二味悄、理論基礎(chǔ)
Git 記錄的是什么草戈?
如上,如果每個版本中有文件發(fā)生變動侍瑟,Git 會將整個文件復制并保存起來唐片。這種設(shè)計看似會多消耗更多的空間,但在分支管理時卻是帶來了很多的益處和便利涨颜。
三棵樹
你的本地倉庫有 Git 維護的三棵“樹”組成费韭,這是 Git 的核心框架。這三棵樹分別是:工作區(qū)域庭瑰、暫存區(qū)域和 Git 倉庫
工作區(qū)域(Working Directory)就是你平時存放項目代碼的地方星持。
暫存區(qū)域(Stage)用于臨時存放你的改動,事實上它只是一個文件弹灭,保存即將提交的文件列表信息督暂。
Git 倉庫(Repository)就是安全存放數(shù)據(jù)的位置,這里邊有你提交的所有版本的數(shù)據(jù)穷吮。其中损痰,HEAD 指向最新放入倉庫的版本(這第三棵樹,確切的說酒来,應(yīng)該是 Git 倉庫中 HEAD 指向的版本)卢未。
Git 的工作流程一般是:
在工作目錄中添加、修改文件堰汉;
將需要進行版本管理的文件放入暫存區(qū)域辽社;
將暫存區(qū)域的文件提交到 Git 倉庫。
因此翘鸭,Git 管理的文件有三種狀態(tài):已修改(modified)滴铅、已暫存(staged)和已提交(committed),依次對應(yīng)上邊的每一個流程就乓。
Git使用教程3---實戰(zhàn)
一汉匙、初始化Git
在自己方便的盤中新建一個文件夾拱烁,這里以MyProject為例,注意路徑中不要含有中文字符噩翠。打開cmd命令窗口戏自,操作如下:
#初始狀態(tài)在C盤中,更改路徑
C:\Users\lenovo>F:
F:\>
F:\>cd MyProject
F:\MyProject>
#初始化Git項目伤锚,成功后創(chuàng)建有一個.git隱藏文件
F:\MyProject>git init
Initialized empty Git repository in F:/MyProject/.git/
#在文件夾MyProject中添加一個文本文件README擅笔,md格式指Markdown格式(建議使用Notepad++編輯)
#然后輸入以下命令將文件加入暫存區(qū)
F:\MyProject>git add README.md
#將文件提交到git倉庫(-m表示添加本次提交的說明,強制要求寫的)
F:\MyProject>git commit -m "add a readme file"
[master (root-commit) 9e08cf4] add a readme file
1 file changed, 1 insertion(+)
create mode 100644 README.md
如何將GItHub上別人的代碼“據(jù)為己有”屯援?
F:\>Clone>git clone 目標
Git使用教程4---狀態(tài)
我們怎么知道哪些文件是新添加的猛们,哪些文件已經(jīng)加入了暫存區(qū)域呢?總不能讓我們自己拿個本本記下來吧狞洋?
當然不弯淘,作為世界上最偉大的版本控制系統(tǒng),你能遇到的囧境吉懊,Git 早已有了相應(yīng)的解決方案庐橙。隨時隨地都可以使用git status查看當前狀態(tài)
F:\MyProject>git status
On branch master
nothing to commit, working tree clean
On branch master: 我們位于一個叫做“master”的分支里,這是默認的分支
nothing to commit, working directory clean : 說明你的工作目錄目前是“干凈的”惕它,沒有需要提交的文件(意思就是自上次提交后怕午,工作目錄中的內(nèi)容壓根兒就沒改動過)。
在工作目錄中添加LICENSE文件(去掉后綴淹魄,用NotePad++打開):
Copyright (C) <year> <copyright holders>
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
小甲魚友情提示:MIT 許可證幾乎是最寬松的版權(quán)約定郁惜,一旦你的程序采用,也就意味著別人只要在軟件包含上邊的版權(quán)聲明甲锡,就可以對你的程序為所欲為了(包括“使用兆蕉、復制、修改缤沦、合并虎韵、出版發(fā)行、散布缸废、再授權(quán)和/或販售軟件及軟件的副本”)包蓝。
輸入git status命令,提示如下:
F:\MyProject>git status
On branch master
Untracked files:
(use "git add <file>..." to include in what will be committed)
LICENSE(紅色)
nothing added to commit but untracked files present (use "git add" to track)
Untracked files 說明存在未跟蹤的文件(下邊紅色的那個)
所謂的“未跟蹤”文件企量,是指那些新添加的并且未被加入到暫存區(qū)域或提交的文件测萎。它們處于一個逍遙法外的狀態(tài),但你一旦將它們加入暫存區(qū)域或提交到 Git 倉庫届巩,它們就開始受到 Git 的“跟蹤”硅瞧。
這里圓括號中的英文是 git 給我們的建議:使用 git add <file> 命令將待提交的文件添加到暫存區(qū)域。
F:\MyProject>git add LICENSE
F:\MyProject>git status
On branch master
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
new file: LICENSE(綠色)
use "git reset HEAD <file>..." to unstage 的意思是“如果你反悔了恕汇,你可以使用 git reset HEAD 命令恢復暫存區(qū)域”腕唧。如果后面接文件名或辖,表示恢復該文件;如果不接文件名枣接,則表示上一次添加的文件颂暇。
F:\MyProject>git reset HEAD
F:\MyProject>git status
On branch master
Untracked files:
(use "git add <file>..." to include in what will be committed)
LICENSE(紅色)
nothing added to commit but untracked files present (use "git add" to track)
再次添加到暫存區(qū)域,然后執(zhí)行 git commit -m "add a license file" 命令:
F:\MyProject>git add LICENSE
F:\MyProject>git status
On branch master
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
new file: LICENSE
F:\MyProject>git commit -m "add a license file"
[master 9fdf9f4] add a license file
1 file changed, 7 insertions(+)
create mode 100644 LICENSE
F:\MyProject>git status
On branch master
nothing to commit, working tree clean
關(guān)于修改
突然發(fā)現(xiàn)版權(quán)那塊忘了寫上自己的名字了……
打開 LICENSE 文件月腋,將 Copyright (C) <year> <copyright holders> 改為 Copyright (C) 2016 FishC蟀架,保存……
執(zhí)行 git status 命令:
F:\MyProject>git status
On branch master
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working directory)
modified: LICENSE(紅色)
no changes added to commit (use "git add" and/or "git commit -a")
由于你對工作目錄的文件進行了修改瓣赂,導致這個文件和暫存區(qū)域的對應(yīng)文件不匹配了榆骚,所以 Git 又給你提出兩條建議:
- 使用 git add 命令將工作目錄的新版本覆蓋暫存區(qū)域的舊版本配乱,然后準備提交
- 使用 git checkout 命令將暫存區(qū)域的舊版本覆蓋工作目錄的新版本(危險操作:相當于丟棄工作目錄的修改)
還有一種情況我們沒分析盟蚣,大家先把新版本的文件覆蓋掉暫存區(qū)域的舊版本:
F:\MyProject>git add LICENSE
F:\MyProject>git status
On branch master
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
modified: LICENSE(綠色)
然后我們打開 LICENSE 文件,將 FishC 改為 FishC.com碘橘,保存……
F:\MyProject>git status
On branch master
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
modified: LICENSE(綠色)
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working directory)
modified: LICENSE(紅色)
這次情況是:被綠的 LICENSE 說明文件存放在暫存區(qū)域(待提交)苫纤,同時紅色的 LICENSE 說明文件還在工作目錄等待添加到暫存區(qū)域碉钠。
這種情況你應(yīng)該意識到這里存在兩個不同版本的 LICENSE 文件,這時如果你直接執(zhí)行 commit 命令卷拘,那么提交的是暫存區(qū)域的版本(FishC)喊废,如果你希望提交工作目錄的新版本(FishC.com),那么你需要先執(zhí)行 add 命令覆蓋暫存區(qū)域栗弟,然后再提交……
一步到位
從工作目錄一步添加到倉庫:git commit -am “說明”
F:\MyProject>git commit -am "change the license file"
-a的意思是add污筷。
git log 查看歷史操作記錄
Git使用教程5---回到過去
有關(guān)回退的命令有兩個:reset 和 checkout
先執(zhí)行g(shù)it log命令,將此時的Git倉庫可視化
三棵樹的情況:
回滾快照
注:快照即提交的版本乍赫,每個版本我們稱之為一個快照瓣蛀。
現(xiàn)在我們利用 reset 命令回滾快照,并看看 Git 倉庫和三棵樹分別發(fā)生了什么雷厂。
執(zhí)行 git reset HEAD~ 命令:
注:HEAD 表示最新提交的快照惋增,而 HEAD~ 表示 HEAD 的上一個快照,HEAD~~表示上上個快照改鲫,如果表示上10個快照诈皿,則可以用HEAD ~10
此時我們的快找回滾到了第二棵數(shù)(暫存區(qū)域)
git reset HEAD~ 命令其實是 git reset --mixed HEAD~ 的縮寫, --mixed 選項是默認的像棘。
默認
git reset HEAD~ 命令其實影響了兩棵樹:首先是移動 HEAD 的指向稽亏,將其指向上一個快照(HEAD~);然后再將該位置的快照回滾到暫存區(qū)域讲弄。
--soft選項
git reset --soft HEAD~ 命令就相當于只移動 HEAD 的指向措左,但并不會將快照回滾到暫存區(qū)域。相當于撤消了上一次的提交(commit)避除。一不小心提交了怎披,后悔了胸嘁,那么你就執(zhí)行 git reset --soft HEAD~ 命令即可(此時執(zhí)行 git log 命令,也不會再看到已經(jīng)撤消了的那個提交)凉逛。
--hard選項
reset 不僅移動 HEAD 的指向性宏,將快照回滾動到暫存區(qū)域,它還將暫存區(qū)域的文件還原到工作目錄状飞。
回滾指定快照
reset 不僅可以回滾指定快照毫胜,還可以回滾個別文件。
命令格式為: git reset 快照 文件名/路徑
這樣诬辈,它就會將忽略移動 HEAD 的指向這一步(因為你只是回滾快照的部分內(nèi)容酵使,并不是整個快照,所以 HEAD 的指向不應(yīng)該發(fā)生改變)焙糟,直接將指定快照的指定文件回滾到暫存區(qū)域口渔。
不僅可以往回滾,還可以往前滾穿撮!
這里需要強調(diào)的是:reset 不僅是一個“復古”的命令缺脉,它不僅可以回到過去,還可以去到“未來”悦穿。
唯一的一個前提條件是:你需要知道指定快照的 ID 號攻礼。
那如果不小心把命令窗口關(guān)了不記得ID號怎么辦?
命令:git reflog
Git記錄的每一次操作的版本ID號
Git使用教程6---版本對比
目的:對比版本之間有哪些不同
準備工作
- 創(chuàng)建一個叫做 MyProject2 的新文件夾作為本次演示的項目栗柒,初始化 Git
- 創(chuàng)建一個 game.py 的文本礁扮,將下邊代碼拷貝進去:
import random
print('------------------我愛魚C工作室------------------')
secret = random.randint(1,10)
temp = input("不妨猜一下小甲魚現(xiàn)在心里想的是哪個數(shù)字:")
guess = int(temp)
while guess != secret:
temp = input("哎呀,猜錯了傍衡,請重新輸入吧:")
guess = int(temp)
if guess == secret:
print("臥槽深员,你是小甲魚心里的蛔蟲嗎?蛙埂!")
print("哼倦畅,猜中了也沒有獎勵!")
else:
if guess > secret:
print("大了绣的,大了~~~")
else:
print("小了叠赐,小了~~~")
print("游戲結(jié)束,不玩啦^_^")
再創(chuàng)建一個 README.md 文件屡江,寫清楚這是一個課后作業(yè)的項目:
課后作業(yè):文字游戲
- 執(zhí)行 git add README.md game.py 命令將文件添加到暫存區(qū)域芭概,接著執(zhí)行 git commit -m "猜數(shù)字游戲" 提交項目的第一個快照
- 更改代碼如下:
import random
print('------------------我愛魚C工作室------------------')
times = 3
secret = random.randint(1,10)
guess = 0
print("不妨猜一下小甲魚現(xiàn)在心里想的是哪個數(shù)字:", end=" ")
while (guess != secret) and (times > 0):
temp = input()
guess = int(temp)
times = times - 1 # 用戶每輸入一次,可用機會就-1
if guess == secret:
print("哇哦惩嘉,你是小甲魚心里的蛔蟲嗎罢洲?!")
print("哼,猜中了也沒有獎勵惹苗!")
else:
if guess > secret:
print("哥殿较,大了大了~~~")
else:
print("嘿,小了桩蓉,小了~~~")
if times > 0:
print("再試一次吧:", end=" ")
else:
print("機會用光咯T_T")
print("游戲結(jié)束淋纲,不玩啦^_^")
更改README文件
《零基礎(chǔ)入門學習Python》第004講
課后作業(yè):文字游戲
比較暫存區(qū)域與工作目錄
直接執(zhí)行 git diff 命令是比較暫存區(qū)域與工作目錄的文件內(nèi)容:
這里可能出現(xiàn)一個問題,直接執(zhí)行的結(jié)果出現(xiàn)中文亂碼院究。在cmd界面的冒號:后面輸入q退出洽瞬,使用Notepad++打開README文件,點擊編碼→轉(zhuǎn)為UTF-8編碼业汰。(舊版本中選擇UTF-8(無BOM)伙窃,新版中的UTF-8默認為無BOM)重新執(zhí)行g(shù)it diff發(fā)現(xiàn)還是不行!怎么肥四蔬胯?对供?在本菜查遍各網(wǎng)站論壇之后位他,終于找到了解決方法
執(zhí)行以下三條命令(別問我明明是四條為啥說三條...)
git config --global i18n.commitencoding utf-8
git config --global i18n.logoutputencoding utf-8
export LESSCHARSET=utf-8 ## linux bash配置環(huán)境變量
set LESSCHARSET=utf-8 #windows配置環(huán)境變量
哈哈哈氛濒,終于搞定了!
現(xiàn)在來解釋一下上面每一行的含義:
第一行:diff --git a/README.md b/README.md
表示對比的是存放在暫存區(qū)域的 README.md 和工作目錄的 README.md
第二行:index 7966837..472a180 100644
表示對應(yīng)文件的 ID 分別是 7966837 和 472a180鹅髓,左邊暫存區(qū)域舞竿,后邊當前目錄。最后的 100644 是指定文件的類型和權(quán)限
第三行:--- a/README.md
--- 表示該文件是舊文件(存放在暫存區(qū)域)
第四行:+++ b/README.md
+++ 表示該文件是新文件(存放在工作區(qū)域)
第五行:@@ -1 +1,2 @@
以 @@ 開頭和結(jié)束窿冯,中間的“-”表示舊文件骗奖,“+”表示新文件,后邊的數(shù)字表示“開始行號醒串,顯示行數(shù)”
第六执桌、七行:
這是將兩個文件合并顯示的結(jié)果,前邊有個 + 的綠色的那一行說明是新文件獨有的芜赌,淺灰色的則是兩個文件所共有的內(nèi)容仰挣。所以,+1,2 表示新文件在合并顯示中從第 1 行開始缠沈,顯示 2 行膘壶。那為啥 -1 后邊沒有顯示的行數(shù)?因為在合并顯示的結(jié)果中洲愤,舊文件已經(jīng)完全包含在新文件中了(也就是舊文件沒有自己“獨有的”內(nèi)容)颓芭。
第八行:\ No newline at end of file
這是 Git 出于善意的提醒:文件不是以換行符結(jié)束。為什么會有這樣多此一舉的提醒呢柬赐?仔細推敲下你就會明白了:diff 將兩個文件合并打印亡问,到達最后一個字符的時候,無論文件中是否存在換行符肛宋,diff 都需要打印一個換行符州藕!為啥万矾?為了好看唄!慎框!所以如果你的文件最后一個字符不是以換行符結(jié)尾良狈,但 diff 又自行添加了一個換行符,所以它覺得有義務(wù)提醒你它這么做了笨枯!
最后的(:)是什么薪丁?
意思是窗口太小,沒辦法顯示全部馅精,正在等待命令(Vim編程知識)
移動命令
j严嗜、k:向下移動一行/向上移動一行
f、b:向下翻頁/向上翻頁
d洲敢、u:向下翻半頁/向上翻半頁
跳轉(zhuǎn)命令
g漫玄、G:跳轉(zhuǎn)到第一行/跳轉(zhuǎn)到最后一行
先輸入數(shù)字(如3),再輸入g压彭,表示跳轉(zhuǎn)到該行(如第3行)
搜索命令
輸入斜杠(/)或問號(?),后面接搜索關(guān)鍵字
區(qū)別:斜杠(/)表示從當前位置向下搜索睦优,問號(?)表示從當前位置向上搜索。
接著輸入 n 表示順著當前的搜索方向快速跳轉(zhuǎn)到下個匹配的位置壮不,大寫的 N 則是與當前搜索方向相反汗盘。
退出和幫助
在點點(:)后邊輸入 q,表示退出 diff询一;輸入 h 表示進入幫助界面隐孽,你會看到很多命令和功能,輸入 q 可以退出幫助界面健蕊。
比較兩個歷史快照
我們執(zhí)行 git commit -am "添加功能:玩家只有三次機會" 命令菱阵,添加并提交工作目錄中的所有文件。執(zhí)行 git log 命令缩功,可以看到現(xiàn)在 Git 倉庫中已經(jīng)有兩個快照了:
執(zhí)行 git diff 6e26975 ed3708c 命令晴及,即可比較 Git 倉庫中兩個快照的差異:
比較當前工作目錄和 Git 倉庫中的快照
我們稍微改動一下 README.md 文件的內(nèi)容:
目前我們的 Git 倉庫應(yīng)該是:
三棵樹是這樣:
比較之前版本的快照與當前工作目錄內(nèi)容
輸入 git diff ed3708c 命令即可
比較當前版本快照與當前工作目錄內(nèi)容
輸入 git diff HEAD 命令即可
比較Git倉庫與暫存區(qū)域
執(zhí)行 git add README.md 命令,將第三版的 README.md 文件添加到暫存區(qū)域掂之。
然后三棵樹就是這樣了:
如果希望比較最新提交的快照和暫存區(qū)域的文件抗俄,只需要執(zhí)行 git diff --cached 命令;當然也可以指定其他快照世舰,就是需要多寫上一個 ID 值动雹,即git diff --cached ID號。
哈哈哈跟压,很亂有木有胰蝠,其實就是這三棵樹之間的相互比較,最后奉上終極奧義圖:
Git使用教程7---修改最后一次提交、刪除文件和重命名文件
問題出現(xiàn):
Situation One:版本剛一提交(commit)到倉庫茸塞,突然想起漏掉兩個文件還沒有添加(add)
Situation Two:版本剛一提交(commit)到倉庫躲庄,突然想起版本說明寫得不夠全面,無法彰顯你本次修改的重大意義……
由于使用reset命令過于繁瑣钾虐,需要提交一個新的版本噪窘,這里可以使用帶 --amend 選項的 commit 命令,(即git commit --amend)Git 會“更正”最近的一次提交效扫。由于這里沒有-m說明倔监,會進入以下頁面:
這個界面其實只是讓你編輯提交說明而已。如果不需要修改菌仁,可以連續(xù)按下兩個大寫Z來退出浩习,或者按下(:)再輸入q!退出,Git會保留舊的提交說明济丘。如果需要提交說明又不想用這么繁瑣的方式谱秽,輸入git commit --ammend -m “新的提交說明” 即可。
刪除文件
問題一:不小心刪除文件怎么辦摹迷?
現(xiàn)在從工作目錄中手動刪除 README.md 文件疟赊,然后執(zhí)行 git status 命令:
提醒使用 checkout 命令可以將暫存區(qū)域的文件恢復到工作目錄:
文件就會重新返回。
問題二:那么如何徹底刪除一個文件呢泪掀?
假如你不小心把小黃圖下載到了工作目錄听绳,然后又不小心提交到了 Git 倉庫:
執(zhí)行 git rm yellow.jpg 命令:
此時工作目錄中的小黃圖(yellow.jpg)已經(jīng)被刪除……
但執(zhí)行 git status 命令,你仍然發(fā)現(xiàn) Git 還不肯松手:
意思是說它在倉庫的快照中發(fā)現(xiàn)有個叫 yellow 的東西异赫,但似乎在暫存區(qū)域和當前目錄不見了!
此時可以執(zhí)行 git reset --soft HEAD~ 命令將快照回滾到上一個位置头岔,然后重新提交塔拳,Git 就不會再提小黃圖的事兒了:
注意:rm 命令刪除的只是工作目錄和暫存區(qū)域的文件(即取消跟蹤,在下次提交時不納入版本管理)
問題三:我在工作目錄中增加一個 test.py 文件峡竣,然后執(zhí)行 git add test.py 命令將其添加到暫存區(qū)域靠抑,此時我修改 test.py 文件的內(nèi)容,那么暫存區(qū)域和工作目錄就是兩個不同的 test.py 文件了适掰,此時如果我執(zhí)行 git rm test.py 命令颂碧,Git 會下意識地阻止我,這是怎么辦类浪?
因為兩個不同內(nèi)容的同名文件载城,誰知道你是不是搞清楚了都要刪掉?還是提醒一下好费就,別等一下出錯了又要賴機器……
根據(jù)提示诉瓦,執(zhí)行 git rm -f test.py 命令就可以把兩個都刪除。
問題四:我只想刪除暫存區(qū)域的文件,保留工作目錄的睬澡,應(yīng)該怎么操作固额?
執(zhí)行 git rm --cached 文件名 命令。
重命名文件
直接在工作目錄重命名文件煞聪,執(zhí)行g(shù)it status出現(xiàn)錯誤:
正確的姿勢應(yīng)該是:
git mv 舊文件名 新文件名
注:Windows 使用 ren 命令修改文件名斗躏,Linux 是使用 mv 命令
教程6彩蛋
如何讓Git 識別某些格式的文件,然后自主不跟蹤它們昔脯?
比如工作目錄中有三個文件1.temp瑟捣、2.temp 和 3.temp,我們不希望后綴名為 temp 的文件被追蹤栅干,可是每次執(zhí)行g(shù)it status都會出現(xiàn):
解決辦法:在工作目錄創(chuàng)建一個名為 .gitignore 的文件迈套。
然后你發(fā)現(xiàn) Windows 壓根兒不允許你在文件管理器中創(chuàng)建以點(.)開頭的文件。windows需要在命令行窗口創(chuàng)建(.)開頭的文件碱鳞。執(zhí)行 echo *.temp > .gitignore 命令桑李,創(chuàng)建一個 .gitignore 文件,并讓 Git 忽略所有 .temp 后綴的文件:
好了窿给,Git 已經(jīng)忽略了所有的 *.temp 文件(你還可以把 .gitignore 文件也一并忽略)贵白。
Git使用教程7---創(chuàng)建和切換分支
分支是什么?
假設(shè)你的大項目已經(jīng)上線了(有上百萬人在使用)崩泡,過了一段時間你突然覺得應(yīng)該添加一些新的功能禁荒,但是為了保險起見,你肯定不能在當前項目上直接進行開發(fā)角撞,這時候你就有創(chuàng)建分支的需要了呛伴。
對于其它版本控制系統(tǒng)而言,創(chuàng)建分支常常需要完全創(chuàng)建一個源代碼目錄的副本谒所,項目越大热康,耗費的時間就越多;而 Git 由于每一個結(jié)點都已經(jīng)是一個完整的項目劣领,所以只需要創(chuàng)建多一個“指針”(像 master)指向分支開始的位置即可姐军。
創(chuàng)建分支
來到之前創(chuàng)建的項目MyProject2,
目前倉庫的狀態(tài)如下:
執(zhí)行g(shù)it status查看狀態(tài):
可以看到 README.md 文件被修改并添加到暫存區(qū)域(還沒有提交)尖淘,所以當前三棵樹應(yīng)該是這樣:
創(chuàng)建分支奕锌,使用 git branch 分支名 命令:
沒有任何提示說明分支創(chuàng)建成功(一般也不會失敗啦,除非創(chuàng)建了同名的分支會提醒你一下)村生,此時可以執(zhí)行 git log --decorate 命令查看:
如果希望以“精簡版”的方式顯示惊暴,可以加上一個 --oneline 選項(即 git log --decorate --oneline),這樣就只用一行來顯示一個快照記錄梆造。
可以看到最新的快照后邊多了一個 (HEAD -> master, feature)
它的意思是:目前有兩個分支缴守,一個是主分支(master)葬毫,一個是剛才我們創(chuàng)建的新分支(feature),然后 HEAD 指針仍然指向默認的 master 分支屡穗。
所以目前倉庫中的快照應(yīng)該是這樣:
切換分支
現(xiàn)在我們需要將工作環(huán)境切換到新創(chuàng)建的分支(feature)上贴捡,使用的就是之前我們欲言又止的 checkout 命令。執(zhí)行 git checkout feature 命令:
這樣 HEAD 指針就指向 feature 分支了:
現(xiàn)在我們進行一次提交(暫存區(qū)域還有一個更改的文件沒有提交呢):
現(xiàn)在倉庫中的快照應(yīng)該是醬紫(提交的快照由當前HEAD指針指向的分支來管理):
然后我們將 HEAD 指針切回 master 分支:
細心的朋友會發(fā)現(xiàn)上一次對 README.md 文件的修改已經(jīng)蕩然無存了村砂,這是因為我們的工作目錄已經(jīng)回到 master 分支的狀態(tài)中:
現(xiàn)在對 README.md 文件進行修改(隨便改改)烂斋,然后執(zhí)行 git commit -m "再次修改說明文件":
目前倉庫中的快照應(yīng)該變成了醬紫:
執(zhí)行 git log --oneline --decorate --graph --all 命令:
--graph 選項表示讓 Git 繪制分支圖,--all 表示顯示所有分支
Git使用教程9---合并和刪除分支
合并分支
當一個子分支的使命完結(jié)之后础废,它就應(yīng)該回歸到主分支中去汛骂。
合并分支我們使用 merge 命令,執(zhí)行 git merge feature 命令评腺,將 feature 分支合并到 HEAD 所在的分支(master)上:
從 Git 提示的內(nèi)容來看帘瞭,我們知道這次的合并并沒有成功,Git 說:
合并 README.md 文件的時候出現(xiàn)沖突蒿讥。
所以自動合并失數睢;請修改沖突的內(nèi)容并重新提交快照芋绸。
意思是說現(xiàn)在你需要先解決沖突的問題媒殉,Git 才能進行合并操作。所謂沖突摔敛,無非就是像兩個分支中存在同名但內(nèi)容卻不同的文件廷蓉,Git 不知道你要舍棄哪一個或保留哪一個,所以需要你自己來決定马昙。
此時執(zhí)行 git status 命令也會顯示需要你解決的沖突:
然后 Git 會在有沖突的文件中加入一些標記桃犬,不信你打開 README.md 文件看看:
以“=======”為界,上到“<<<<<<< HEAD”的內(nèi)容表示當前分支给猾,下到“>>>>>>> feature”表示待合并的 feature 分支疫萤,之間的內(nèi)容就是沖突的地方。
現(xiàn)在我們將 README.md 統(tǒng)一修改(去掉 <<<<<<< HEAD 等內(nèi)容)
保存文件敢伸,然后提交快照:
執(zhí)行 git log --decorate --all --graph --oneline 命令,可以看到此時的分支已經(jīng)自動合并了:
當然恒削,如果不存在沖突池颈,就不用搞這么多了……舉個例子:
執(zhí)行 git checkout -b feature2 命令(相當于 git branch feature2 和 git checkout feature2 兩個命令的合體):
在工作目錄隨便創(chuàng)建一個文本文件(feature2.txt)并提交快照:
執(zhí)行 git log --decorate --all --graph --oneline 命令:
可以看到,feature2 分支比 master 分支快了一步〉龇幔現(xiàn)在我們切換回 master 分支躯砰,并將 feature2 分支合并進來:
這次 Git 只顯示了 Fast-forward(快進)這詞兒,這是因為 feature2 這個分支的父結(jié)點是 master 分支携丁,所以 Git 只需要簡單移動 master 的指向即可琢歇。
執(zhí)行 git log --decorate --all --graph --oneline 命令:
刪除分支
刪除分支兰怠,使用 git branch -d 分支名 命令:
執(zhí)行 git log --decorate --all --graph --oneline 命令:
由于 Git 的分支原理實際上只是通過一個指針記載,所以創(chuàng)建和刪除分支都幾乎是瞬間完成李茫。
注意:如果試圖刪除未合并的分支揭保,Git 會提示你“該分支未完全合并,如果你確定要刪除魄宏,請使用 git branch -D 分支名 命令秸侣。
彩蛋:Git的兩種合并方式 --- Fast-forward 和 Three-way merge
Fast-forward
所謂的 Fast-forward 就是當待合并的分支位于目標分支的直接上游時,Git 只需把目標分支的指針直接移動即可實現(xiàn)合并宠互。
比如下面圖片中 master 分支是位于 feature2 分支的直接上游:
將 feature2 分支合并到 master 分支味榛,只需要移動 master 的指針即可:
Three-way merge
如果待合并的兩個分支不在同一條線上,那么進行合并就需要解決一個根本的問題 —— 沖突予跌!
為何兩個分支在同一條線上就不會沖突呢搏色?
因為 Git 的快照是按時間順序提交的,所以在同一條線上的兩個快照券册,它們是有先后順序的频轿,盡管兩者可能出現(xiàn)同名文件不同內(nèi)容,Git 會認為這是“改變”而不是“沖突”汁掠。
舉個例子:
合并 C3 和 C4 得到 C5略吨,但 C5 應(yīng)該如何處理“沖突”呢?
SVN 會把問題拋給用戶考阱,讓用戶自行解決电禀;Git 則顯得更為高明背桐,它會找到第三個快照,然后綜合三者特點自動解決沖突。
那第三個快照應(yīng)該如何決定呢劲装?
沒錯,應(yīng)該找兩者的共同“祖先”作為參照物斧蜕,一比較就知道兩個分支都干了些什么号显。
圖片中 C3 和 C4 的共同祖先是 C1,可以看到 C3 和 C4 分別增加了 test2.py 和 test1.py 兩個文件鹦倚。因為對比之后發(fā)現(xiàn)三者并沒有沖突河质,所以 C5 應(yīng)該是三者的合體,即同時擁有 common.py震叙、test1.py 和 test2.py 三個文件掀鹅。
另外,值得一提的是媒楼,Git 這種合并方式也適用于同名文件的不同更改乐尊。
舉個例子:
這里 C3 和 C4 都只有一個文件(test.txt),但是內(nèi)容卻不一樣划址。如果這樣合并扔嵌,你猜 Git 會不會報“沖突”限府?
答案是不會的!
因為 Git 找到它們的共同祖先 C1痢缎,可以看到 C3 和 C4 都是在 C1 的基礎(chǔ)上進行添加(C4 在第 2 行添加了“I”胁勺,C3 在第 4 行增加了“FishC”,C1 第 3 行的“l(fā)ove”是它們共同擁有的)牺弄,同時在每一行并沒有產(chǎn)生沖突的地方姻几,所以自動合并后的 C5 是這樣的:
# test.txt
I
love
FishC
注意:如果 Git 檢測到同一行有不同的內(nèi)容,還是會報沖突并讓你自行決定誰去誰留的势告!
Git使用教程10---匿名分支和checkout命令
匿名分支
創(chuàng)建一個新的文件夾(MyProject3)蛇捌,然后初始化 git。依次創(chuàng)建三個文件并提交(每創(chuàng)建一個文件提交一次):
上一節(jié)課我們講的是使用 branch 命令創(chuàng)建一個分支咱台,然后使用 checkout 命令切換分支络拌。
如果在沒創(chuàng)建分支的情況下執(zhí)行 checkout 命令,會有怎樣的事情發(fā)生呢回溺?
我們不妨試試看春贸,執(zhí)行 git checkout HEAD~ 命令:
當前的 HEAD 指針處于分離狀態(tài),你可以環(huán)顧四周遗遵,做一些實驗性修改并提交它們萍恕,并且你可以在這個狀態(tài)中丟棄任何你所做的提交,而不影響任何分支车要,做法是執(zhí)行 checkout 命令切換回別的分支允粤。
如果你希望創(chuàng)建一個新分支,并保持你所做創(chuàng)建的提交翼岁,你可以(現(xiàn)在或稍后)通過使用帶有 -b 選項的 checkout 命令實現(xiàn)类垫。例如:
git checkout -b <new-branch-name>
HEAD 指針當前指向 52861cf... 2.txt
你使用了 checkout 命令但沒有指定分支名,所以 Git 幫你創(chuàng)建了一個匿名分支琅坡,OK悉患,既然是匿名,那么當你切換到別的分支時榆俺,這個匿名分支中的所有提交都會被丟棄掉(因為你都沒給人家命名售躁,反正以后都找不回了,不丟了干啥茴晋?)迂求。因此,你可以利用匿名分支來做做實驗什么的晃跺,反正不會有負面影響。
來毫玖,我們試試掀虎,在工作目錄中創(chuàng)建一個 4.txt(你會發(fā)現(xiàn) 3.txt 不見了凌盯,這是因為 checkout 將環(huán)境切換到上一次提交了),然后提交
執(zhí)行 git log --decorate --all --graph --oneline 命令
可以看到有兩個分支烹玉,但 HEAD 所在的分支并沒有名字(匿名分支)驰怎,那現(xiàn)在我們把 HEAD 切回 master 分支:
警告:你殘留一個沒有連接任何分支的提交:
178d909 4.txt
如果你想通過創(chuàng)建一個分支來連接它,這將是一個好時機二打,請執(zhí)行:
git branch <new-branch-name> 178d909
已經(jīng)切換到 'master' 分支
現(xiàn)在再來查看提交日志县忌,可以看到匿名分支已經(jīng)蕩然無存:
再論checkout
事實上呢,checkout 命令有兩種功能:
- 從歷史快照(或者暫存區(qū)域)中拷貝文件到工作目錄
- 切換分支
從歷史快照(或者暫存區(qū)域)中拷貝文件到工作目錄
當給定某個文件名時继效,Git 會從指定的提交中拷貝文件到暫存區(qū)域和工作目錄症杏。比如執(zhí)行 git checkout HEAD~ README.md 命令會將上一個快照中的 README.md 文件復制到工作目錄和暫存區(qū)域中:
如果命令中沒有指定具體的快照 ID,則將從暫存區(qū)域恢復指定文件到工作目錄(git checkout README.md):
有些朋友可能會問:“上次看你在文件名的前邊有加兩個橫桿(--)瑞信,這次怎么就沒有了呢厉颤?”
問得好,Git 提醒你寫成 git checkout -- README.md 的形式凡简,那是為了預防你恰好有一個分支叫做 README.md逼友,那么它就搞不懂你要恢復文件還是切換分支了,所以約定兩個橫桿(--)后邊跟的是文件名秤涩。
反過來說帜乞,如果你確保你沒有一個叫做 README.md 的分支,你直接寫 git checkout README.md 也是妥妥的沒問題啦
切換分支
首先我們知道 Git 的分支其實就是添加一個指向快照的指針筐眷,其次我們還知道切換分支除了修改 HEAD 指針的指向黎烈,還會改變暫存區(qū)域和工作目錄的內(nèi)容。
所以執(zhí)行 git checkout 373c0 命令浊竟,Git 主要就是做了下邊這兩件事(當然事實上 Git 還做了更多):
那回過頭來怨喘,如果我們只想恢復指定的文件/路徑,那么我們只需要指定具體的文件振定,Git 就會忽略第一步修改 HEAD 指向的操作必怜,這不正跟之前講 reset 命令的時候一樣嗎?
checkout 命令和 reset 命令的區(qū)別
恢復文件
checkout 命令和 reset 命令都可以用于恢復指定快照的指定文件后频,并且它們都不會改變 HEAD 指針的指向梳庆。
下面開始劃重點:
它們的區(qū)別是 reset 命令只將指定文件恢復到暫存區(qū)域(--mixed),而 checkout 命令是同時覆蓋暫存區(qū)域和工作目錄卑惜。
注意:也許你試圖使用 git reset --hard HEAD~ README.md 命令讓 reset 同時覆蓋工作目錄膏执,但 Git 會告訴你這是徒勞(此時 reset 不允許使用 --soft 或 --hard 選項)。
這樣看來露久,在恢復文件方面更米,reset 命令要比 checkout 命令更安全一些。
恢復快照
reset 命令是用來“回到過去”的毫痕,根據(jù)選項的不同征峦,reset 命令將移動 HEAD 指針(--soft) -> 覆蓋暫存區(qū)域(--mixed迟几,默認)-> 覆蓋工作目錄(--hard)。
checkout 命令雖說是用于切換分支栏笆,但前面你也看到了类腮,它事實上也是通過移動 HEAD 指針和覆蓋暫存區(qū)域、工作目錄來實現(xiàn)的蛉加。
那問題來了:它們有什么區(qū)別呢蚜枢?
下面開始劃重點:
第一個區(qū)別是,對于 reset --hard 命令來說针饥,checkout 命令更安全厂抽。因為 checkout 命令在切換分支前會先檢查一下當前的工作狀態(tài),如果不是“clean”的話打厘,Git 不會允許你這樣做修肠;而 reset --hard 命令則是直接覆蓋所有數(shù)據(jù)。
另一個區(qū)別是如何更新 HEAD 指向户盯,reset 命令會移動 HEAD 所在分支的指向嵌施,而 checkout 命令只會移動 HEAD 自身來指向另一個分支。
看文字你肯定懵莽鸭,我們舉例說明吗伤。
來,大家先把剛才的例子改成下邊這樣:
執(zhí)行 git checkout feature 命令:
可以看到只是 HEAD 指針跑到 feature 分支那兒去了硫眨。
好足淆,我們執(zhí)行 git checkout master 命令將其切回。
現(xiàn)在執(zhí)行 git reset --hard feature 命令:
彩蛋
通常情況下礁阁,Git 會盡可能地嘗試使用 Fast-forward 方式來合并分支巧号,因為這樣效率非常高,只有在萬不得已的時候才使用三方合并(Three-way merge)
但是姥闭,有時候 Fast-forward 的方式卻很容易讓我們忽略了分支的存在丹鸿!
舉個例子,比如下面這樣:
如果我們把“feature”分支刪除棚品,就會直接丟掉分支的信息:
根本就不知道有個分支存在過……
可有時候我們確實希望保留分支的信息靠欢,應(yīng)該怎么辦呢?
只需要在 merge 的時候使用 --no-ff 選項即可告訴 Git 不要使用 Fast-forward 方式合并分支铜跑。
這樣 Git 就會乖乖地使用三方合并(Three-way merge):
OK门怪,這樣就算刪掉了“feature”分支,我們?nèi)匀豢梢院苋菀卓闯鲇袀€分支曾經(jīng)存在過:
Git使用教程到這里就告一段落了锅纺,隨后會可能會更新小甲魚翻譯的Github官方教程奧~~~