- 全局配置
$ git config --global user.name "Your Name"
$ git config --global user.email "email@example.com"
- 初始化
git init
- 添加到暫存區(qū)
//git add a.txt
git add .
- 添加到本地的版本庫(kù)
git commit -m 'des'
- 查看當(dāng)前的狀態(tài)
git status
- 打印commit記錄
git log
//git log --pretty=oneline
- 回退版本
git reset --hard HEAD^
git reset --hard HEAD^^
git reset --hard 'commit id'
- 查看所有記錄
git reflog
- 撤銷修改
場(chǎng)景1:當(dāng)你改亂了工作區(qū)某個(gè)文件的內(nèi)容歹颓,想直接丟棄工作區(qū)的修改時(shí)油湖,用命令git checkout -- file
乏德。
場(chǎng)景2:當(dāng)你不但改亂了工作區(qū)某個(gè)文件的內(nèi)容,還添加到了暫存區(qū)時(shí)寂呛,想丟棄修改瘾晃,分兩步蹦误,第一步用命令git reset HEAD file
肉津,就回到了場(chǎng)景1舱沧,第二步按場(chǎng)景1操作熟吏。
場(chǎng)景3:已經(jīng)提交了不合適的修改到版本庫(kù)時(shí),想要撤銷本次提交悍引,參考版本回退一節(jié)帽氓,不過(guò)前提是沒(méi)有推送到遠(yuǎn)程庫(kù)
- 刪除文件
rm a.txt
git status
// 1 確認(rèn)要?jiǎng)h除
git rm a.txt
git commit -m 'des'
// 2刪錯(cuò)黎休,想要回退
$ git checkout -- test.txt
git checkout
其實(shí)是用版本庫(kù)里的版本替換工作區(qū)的版本,無(wú)論工作區(qū)是修改還是刪除联贩,都可以“一鍵還原”撑蒜。
命令git rm
用于刪除一個(gè)文件玄渗。如果一個(gè)文件已經(jīng)被提交到版本庫(kù),那么你永遠(yuǎn)不用擔(dān)心誤刪浴滴,但是要小心升略,你只能恢復(fù)文件到最新版本屡限,你會(huì)丟失最近一次提交后你修改的內(nèi)容。
- 創(chuàng)建
ssh key
先查看用戶主目錄下有沒(méi)有.ssh
如果有進(jìn)入翰撑,查看id_rsa
(私鑰),id_rsa.pub
(公鑰)眶诈,使用的事公鑰,
cat id_rsa.pub
如果沒(méi)有.ssh浴骂,則需要?jiǎng)?chuàng)建
$ ssh-keygen -t rsa -C "youremail@example.com"
- 添加遠(yuǎn)程倉(cāng)庫(kù)
$ git remote add origin git@github.com:<your name>/learngit.git
$ git push -u origin master
Counting objects: 19, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (19/19), done.
Writing objects: 100% (19/19), 13.73 KiB, done.
Total 23 (delta 6), reused 0 (delta 0)
To git@github.com:michaelliao/learngit.git
* [new branch] master -> master
Branch master set up to track remote branch master from origin.
由于遠(yuǎn)程庫(kù)是空的溯警,我們第一次推送master分支時(shí)坎炼,加上了-u參數(shù)谣光,Git不但會(huì)把本地的master分支內(nèi)容推送的遠(yuǎn)程新的master分支芬为,還會(huì)把本地的master分支和遠(yuǎn)程的master分支關(guān)聯(lián)起來(lái)媚朦,在以后的推送或者拉取時(shí)就可以簡(jiǎn)化命令。
$ git push origin master
- 從遠(yuǎn)端克隆
$ git clone
- 創(chuàng)建與合并分支
// 創(chuàng)建并且切換分支到dev
git checkout -b dev
// 等同于
git branch dev
git checkout dev
git status
*dev
master
git add .
git commit -m 'des'
git checkout master
git merge dev
git checkout dev
// 刪除dev分支
git branch -d dev
這次合并是“快進(jìn)模式”孙乖,也就是直接把master指向dev的當(dāng)前提交份氧,所以合并速度非澄现模快。
- 解決沖突
git branch -b feature1
修改read.txt
git add .
git commit -m 'and'
git checkout master
在master read.txt也修改
git add .
git commit -m 'AND'
git merge dev
就會(huì)產(chǎn)生沖突
git status
<<<<<<< HEAD
Creating a new branch is quick AND simple.
=======
Creating a new branch is quick and simple.
>>>>>>> feature1
然后保留一個(gè)修改蔬顾,刪除另一個(gè)
git add .
git commit -m 'merge'
// 查看合并情況
git log --graph --pretty=oneline --abbrev-commit
// 刪除分支feature1
git branch -d feature
- 分支管理策略
通常诀豁,合并分支時(shí)窥妇,如果可能,Git會(huì)用Fast forward模式逞带,但這種模式下展氓,刪除分支后,會(huì)丟掉分支信息未妹。
如果要強(qiáng)制禁用Fast forward
模式空入,Git就會(huì)在merge時(shí)生成一個(gè)新的commit歪赢,這樣,從分支歷史上就可以看出分支信息点楼。
下面我們實(shí)戰(zhàn)一下--no-ff
方式的git merge:
首先白对,仍然創(chuàng)建并切換dev分支
git branch -b dev
// 修改一些文件
git add .
git commit -m 'done'
git checkout master
使用 --no-ff
合并分支
git merger --no-ff -m '--no-ff merger test' dev
// 查看合并的狀態(tài)
$ git log --graph --pretty=oneline --abbrev-commit
* 7825a50 --no-ff merger test
|\
| * 6224937 done
|/
* 59bc1cb conflict fixed
...
- bug分支
在dev分支開(kāi)發(fā)是甩恼,工作到一半的時(shí)候,可能還需要一定時(shí)間才能完成(還未提交)悦污,但是此時(shí)此需要一個(gè)小時(shí)來(lái)解決一個(gè)Bug
可以是使用
git stash
把現(xiàn)在的工作現(xiàn)場(chǎng)保存起來(lái)在使用git status
就會(huì)發(fā)現(xiàn)工作區(qū)是clear的
然后選定在哪個(gè)分支上進(jìn)行修改bug塞关,這里假設(shè)是在master分支上修改的
git checkout master
git branch -b issue101
// 假設(shè)已經(jīng)修改了一些代碼
git add .
git commit -m 'done'
// 合并
git checkout master
git merge --no-ff -m 'issue-101 fixed' issue101
此時(shí)bug修改完畢,切換到dev分支
git checkout dev
git status
會(huì)發(fā)現(xiàn)dev分支的工作區(qū)是clear的
git stash list
stash@{0}: WIP on dev: 6224937 add merge
工作現(xiàn)場(chǎng)還在帆赢,Git把stash內(nèi)容存在某個(gè)地方了线梗,但是需要恢復(fù)一下,有兩個(gè)辦法:
一是用git stash apply
恢復(fù)瘾婿,但是恢復(fù)后偏陪,stash內(nèi)容并不刪除,你需要用git stash drop
來(lái)刪除抱虐;
另一種方式是用git stash pop
饥脑,恢復(fù)的同時(shí)把stash內(nèi)容也刪了:
git stash pop
git stash list
//會(huì)發(fā)現(xiàn)是空的
你可以多次stash灶轰,恢復(fù)的時(shí)候,先用git stash list查看乳附,然后恢復(fù)指定的stash许溅,用命令:
$ git stash apply stash@{0}
- feature分支
新的功能
git checkout -b feature2
一段時(shí)間后開(kāi)發(fā)完成
git add .
git commit -m 'feature'
// 切回到dev分支
git checkout dev
由于種種原因 決定放棄這個(gè)功能(但是此時(shí)還沒(méi)合并分支)
git branch -d feature2
error: The branch 'feature2' is not fully merged.
If you are sure you want to delete it, run 'git branch -D feature2'.
$ git branch -D feature1
Deleted branch feature1 (was 756d4af).
- 多人協(xié)作
查看遠(yuǎn)程分支
git remote
origin
或者
git remote -v
origin git@github.com:<name>/<project-name>.git (fetch)
origin git@github.com:<name>/<project-name>.git (push)
上面顯示了可以抓取和推送的origin的地址。如果沒(méi)有推送權(quán)限茬祷,就看不到push的地址祭犯。
A小伙伴:
git clone ......
克隆下來(lái)的項(xiàng)目只能看見(jiàn)master分支
git branch
* master
現(xiàn)在,你的小伙伴要在dev分支上開(kāi)發(fā)粥惧,就必須創(chuàng)建遠(yuǎn)程origin的dev分支到本地突雪,于是他用這個(gè)命令創(chuàng)建本地dev分支:
git checkout -b dev origin/dev
A小伙伴就可在dev分支上進(jìn)行修改等等涡贱,比如
git add .
git commit -m ''
git push origin master
就在此時(shí)问词,我要對(duì)同一個(gè)地方進(jìn)行了修改,并且要提交
git add hello.py
git commit -m 'add python'
git push origin dev
會(huì)發(fā)現(xiàn)推送失敗了辰狡;因?yàn)槟愕男』锇榈淖钚绿峤缓湍阍噲D推送的提交有沖突宛篇,解決辦法也很簡(jiǎn)單,Git已經(jīng)提示我們豌鸡,先用git pull把最新的提交從origin/dev抓下來(lái)段标,然后逼庞,在本地合并,解決沖突派任,再推送:
git pull
remote: Counting objects: 5, done.
remote: Compressing objects: 100% (2/2), done.
remote: Total 3 (delta 0), reused 3 (delta 0)
Unpacking objects: 100% (3/3), done.
From github.com:michaelliao/learngit
fc38031..291bea8 dev -> origin/dev
There is no tracking information for the current branch.
Please specify which branch you want to merge with.
See git-pull(1) for details
git pull <remote> <branch>
If you wish to set tracking information for this branch you can do so with:
git branch --set-upstream dev origin/<branch>
還是失敗了,原因是沒(méi)有指定本地dev分支與遠(yuǎn)程origin/dev分支的鏈接掌逛,根據(jù)提示司倚,設(shè)置dev和origin/dev的鏈接
$ git pull
Auto-merging hello.py
CONFLICT (content): Merge conflict in hello.py
Automatic merge failed; fix conflicts and then commit the result.
這回git pull成功动知,但是合并有沖突盒粮,需要手動(dòng)解決,解決的方法和分支管理中的解決沖突完全一樣妒穴。解決后,提交种呐,再push:
$ git commit -m "merge & fix hello.py"
[dev adca45d] merge & fix hello.py
$ git push origin dev
Counting objects: 10, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (5/5), done.
Writing objects: 100% (6/6), 747 bytes, done.
Total 6 (delta 0), reused 0 (delta 0)
To git@github.com:michaelliao/learngit.git
291bea8..adca45d dev -> dev
- 忽略文件
有些時(shí)候宰翅,你必須把某些文件放到Git工作目錄中,但又不能提交它們爽室,比如保存了數(shù)據(jù)庫(kù)密碼的配置文件啦汁讼,等等淆攻,每次git status都會(huì)顯示Untracked files ...,有強(qiáng)迫癥的童鞋心里肯定不爽嘿架。
好在Git考慮到了大家的感受瓶珊,這個(gè)問(wèn)題解決起來(lái)也很簡(jiǎn)單耸彪,在Git工作區(qū)的根目錄下創(chuàng)建一個(gè)特殊的.gitignore文件伞芹,然后把要忽略的文件名填進(jìn)去,Git就會(huì)自動(dòng)忽略這些文件蝉娜。
不需要從頭寫.gitignore文件唱较,GitHub已經(jīng)為我們準(zhǔn)備了各種配置文件,只需要組合一下就可以使用了召川。所有配置文件可以直接在線瀏覽:https://github.com/github/gitignore
忽略文件的原則是:
忽略操作系統(tǒng)自動(dòng)生成的文件南缓,比如縮略圖等;
忽略編譯生成的中間文件荧呐、可執(zhí)行文件等汉形,也就是如果一個(gè)文件是通過(guò)另一個(gè)文件自動(dòng)生成的,那自動(dòng)生成的文件就沒(méi)必要放進(jìn)版本庫(kù)倍阐,比如Java編譯產(chǎn)生的.class文件概疆;
忽略你自己的帶有敏感信息的配置文件,比如存放口令的配置文件峰搪。
舉個(gè)例子:
假設(shè)你在Windows下進(jìn)行Python開(kāi)發(fā)岔冀,Windows會(huì)自動(dòng)在有圖片的目錄下生成隱藏的縮略圖文件,如果有自定義目錄罢艾,目錄下就會(huì)有Desktop.ini文件楣颠,因此你需要忽略Windows自動(dòng)生成的垃圾文件:
Windows:
Thumbs.db
ehthumbs.db
Desktop.ini
然后,繼續(xù)忽略Python編譯產(chǎn)生的.pyc咐蚯、.pyo、dist等文件或目錄:
Python:
*.py[cod]
*.so
*.egg
*.egg-info
dist
build
加上你自己定義的文件弄贿,最終得到一個(gè)完整的.gitignore文件春锋,內(nèi)容如下:
Windows:
Thumbs.db
ehthumbs.db
Desktop.ini
Python:
*.py[cod]
*.so
*.egg
*.egg-info
dist
build
My configurations:
db.ini
deploy_key_rsa
最后一步就是把.gitignore也提交到Git,就完成了差凹!當(dāng)然檢驗(yàn).gitignore的標(biāo)準(zhǔn)是git status命令是不是說(shuō)working directory clean期奔。
使用Windows的童鞋注意了,如果你在資源管理器里新建一個(gè).gitignore文件危尿,它會(huì)非常弱智地提示你必須輸入文件名呐萌,但是在文本編輯器里“保存”或者“另存為”就可以把文件保存為.gitignore了。
有些時(shí)候谊娇,你想添加一個(gè)文件到Git肺孤,但發(fā)現(xiàn)添加不了,原因是這個(gè)文件被.gitignore忽略了:
$ git add App.class
The following paths are ignored by one of your .gitignore files:
App.class
Use -f if you really want to add them.
如果你確實(shí)想添加該文件,可以用-f強(qiáng)制添加到Git:
$ git add -f App.class
或者你發(fā)現(xiàn)赠堵,可能是.gitignore寫得有問(wèn)題小渊,需要找出來(lái)到底哪個(gè)規(guī)則寫錯(cuò)了,可以用git check-ignore命令檢查:
$ git check-ignore -v App.class
.gitignore:3:*.class App.class
Git會(huì)告訴我們茫叭,.gitignore的第3行規(guī)則忽略了該文件酬屉,于是我們就可以知道應(yīng)該修訂哪個(gè)規(guī)則。
小結(jié)
忽略某些文件時(shí)揍愁,需要編寫.gitignore呐萨;
.gitignore文件本身要放到版本庫(kù)里,并且可以對(duì).gitignore做版本管理莽囤!
- 配置別名
有沒(méi)有經(jīng)常敲錯(cuò)命令垛吗?比如git status?status這個(gè)單詞真心不好記烁登。
如果敲git st就表示git status那就簡(jiǎn)單多了怯屉,當(dāng)然這種偷懶的辦法我們是極力贊成的。
我們只需要敲一行命令饵沧,告訴Git锨络,以后st就表示status:
$ git config --global alias.st status
好了,現(xiàn)在敲git st看看效果狼牺。
當(dāng)然還有別的命令可以簡(jiǎn)寫羡儿,很多人都用co表示checkout,ci表示commit是钥,br表示branch:
$ git config --global alias.co checkout
$ git config --global alias.ci commit
$ git config --global alias.br branch
以后提交就可以簡(jiǎn)寫成:
$ git ci -m "bala bala bala..."
--global參數(shù)是全局參數(shù)掠归,也就是這些命令在這臺(tái)電腦的所有Git倉(cāng)庫(kù)下都有用。
在撤銷修改一節(jié)中悄泥,我們知道虏冻,命令git reset HEAD file可以把暫存區(qū)的修改撤銷掉(unstage),重新放回工作區(qū)弹囚。既然是一個(gè)unstage操作厨相,就可以配置一個(gè)unstage別名:
$ git config --global alias.unstage 'reset HEAD'
當(dāng)你敲入命令:
$ git unstage test.py
實(shí)際上Git執(zhí)行的是:
$ git reset HEAD test.py
配置一個(gè)git last,讓其顯示最后一次提交信息:
$ git config --global alias.last 'log -1'
這樣鸥鹉,用git last就能顯示最近一次的提交:
$ git last
commit adca45d317e6d8a4b23f9811c3d7b7f0f180bfe2
Merge: bd6ae48 291bea8
Author: Michael Liao <askxuefeng@gmail.com>
Date: Thu Aug 22 22:49:22 2013 +0800
merge & fix hello.py
甚至還有人喪心病狂地把lg配置成了:
git config --global alias.lg "log --color --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit"
來(lái)看看git lg的效果:
git-lg
為什么不早點(diǎn)告訴我蛮穿?別激動(dòng),咱不是為了多記幾個(gè)英文單詞嘛毁渗!
配置文件
配置Git的時(shí)候践磅,加上--global是針對(duì)當(dāng)前用戶起作用的,如果不加灸异,那只針對(duì)當(dāng)前的倉(cāng)庫(kù)起作用府适。
配置文件放哪了羔飞?每個(gè)倉(cāng)庫(kù)的Git配置文件都放在.git/config文件中:
$ cat .git/config
[core]
repositoryformatversion = 0
filemode = true
bare = false
logallrefupdates = true
ignorecase = true
precomposeunicode = true
[remote "origin"]
url = git@github.com:michaelliao/learngit.git
fetch = +refs/heads/*:refs/remotes/origin/*
[branch "master"]
remote = origin
merge = refs/heads/master
[alias]
last = log -1
別名就在[alias]后面,要?jiǎng)h除別名细溅,直接把對(duì)應(yīng)的行刪掉即可褥傍。
而當(dāng)前用戶的Git配置文件放在用戶主目錄下的一個(gè)隱藏文件.gitconfig中:
$ cat .gitconfig
[alias]
co = checkout
ci = commit
br = branch
st = status
[user]
name = Your Name
email = your@email.com
配置別名也可以直接修改這個(gè)文件,如果改錯(cuò)了喇聊,可以刪掉文件重新通過(guò)命令配置恍风。
坑
refusing to merge unrelated histories
解決方法
git pull --allow-unrelated-histories
通過(guò)廖雪峰老師的git教程,又重新學(xué)習(xí)了一遍