寫(xiě)這個(gè)東西一為了總結(jié)思路,二為了在公司內(nèi)部的講演嘶窄。
耳熟能詳
概念
操作
- git init
- git clone
- git pull
- git fetch
- git merge
- git branch
- git reset
- git revert
- git reflog
- git log
- git config
初次見(jiàn)面
設(shè)置賬戶
git config
git config --global user.name "Manjack" user.email "manjack@aobi.com"
就算不加上--global
參數(shù)哭廉,也會(huì)設(shè)置到全局變量里脊僚,沒(méi)辦法對(duì)某個(gè)repo設(shè)置name和email。
config文件有三個(gè)層次:
- repo層面的遵绰,保存在每個(gè)repo的.git文件夾里
[remote "origin"]
url = https://github.com/wangshub/wechat_jump_game.git
fetch = +refs/heads/*:refs/remotes/origin/*
[branch "master"]
remote = origin
merge = refs/heads/master
- 用戶層面的辽幌,保存在
C:/user/<user-name>/.gitconfig
[user]
email = exkulo@qq.com
name = ManjackGo
- 系統(tǒng)層面,做一些全局設(shè)定街立,比如<別名><默認(rèn)行為(比如fetch使用merge還是rebase)>
C:/ProgramData/git/config
生成sshkey
和服務(wù)器采用非對(duì)稱加密進(jìn)行校驗(yàn)舶衬,需要把公鑰上傳至服務(wù)器自己的賬號(hào)里埠通。使用代碼:
ssh-keygen -t rsa -C "manjack@aobi.com"
三次回車使用默認(rèn)值赎离。公鑰會(huì)保存在:
- windows
C:\Users\<user-name>\.ssh/id_rsa.pub
- UNIX/MAC
~ /.gitconfig
把文件里的內(nèi)容全選(必須包括最后一行的空行)粘貼到自己gitlab賬戶的ssh密鑰里面,完成配置端辱。
建立一個(gè)repository
一梁剔、自己建立一個(gè)空repo
隨便在某個(gè)文件夾使用git init
虽画。可以看到生成了一個(gè).git文件夾荣病。git自動(dòng)幫我們建立了一條叫做master的分支码撰。
二、從網(wǎng)上clone一個(gè)repo
- 從網(wǎng)上的repo拿到一個(gè)遠(yuǎn)端網(wǎng)址
- 執(zhí)行
git clone <url>
可以得到一個(gè)新的repo个盆,并幫我們把url設(shè)置為一個(gè)名字為remote
的遠(yuǎn)端脖岛。
相當(dāng)于執(zhí)行了以下操作:
git remote add remote <url>
git pull
.git文件夾
hooks # 鉤子函數(shù)存放點(diǎn),可使用自己喜歡的腳本寫(xiě)
|
pre-commit
pre-push
info
|
exclude # 一個(gè)本地版本的.ignore
objectsm #存放著歷史文件颊亮,包括版本本身柴梆,以及版本對(duì)應(yīng)的文件
|
21
c4
b5
...
refs
|
heads
|
master
nb
remotes
|
remote
tags
|
release1.0.0
config
description
HEAD #代表當(dāng)前的版本指向
版本的實(shí)質(zhì)
當(dāng)我們完成一次commit操作,實(shí)質(zhì)上發(fā)生了:
- 把當(dāng)前版本變動(dòng)的文件壓縮终惑,產(chǎn)生hash作為名稱
- 把這些文件的hash集合起來(lái)绍在,hash一次
- 把當(dāng)前狀態(tài)的head進(jìn)行一次哈希,作為本次提交的tree
- 給當(dāng)前的提交一個(gè)hash值雹有,作為log的版本號(hào)
以上所有的文件均儲(chǔ)存在object文件里偿渡,文件夾的兩個(gè)字母作為一串hash碼的頭兩個(gè)字母,文件夾里的文件名是hash另外一部分的字符串霸奕。
可以使用
git cat-file -p <file-name>
來(lái)解壓查看文件溜宽。
(演示ING...)
提交代碼
working, stage, head
解釋...
add
-
git add .
把當(dāng)前目錄的變動(dòng)提交到stage區(qū) -
git add
<file-name>
commit
git commit
vim基礎(chǔ)操作
安裝的時(shí)候默認(rèn)使用vim作為編輯器,在這里基本只要知道以下幾個(gè)點(diǎn)就可以用了:
- i進(jìn)入編輯模式
- esc退出編輯模式
- wq保存并退出
git commit -m "<message>"
-
git commit --amend <message>
添加本次提交到上一次的提交质帅,并修改上一次提交的log(若沒(méi)有得提交則只改log)
所謂版本坑质,tag,branch
只是一個(gè)代表著某個(gè)版本的字符串临梗。保存在refs里面涡扼,打開(kāi)可以看到所對(duì)應(yīng)的字符串。所謂的撤回操作盟庞,就是返回到某個(gè)版本吃沪。而HEAD代表著當(dāng)前工作目錄所對(duì)應(yīng)的分支或者版本。
(展示HEAD什猖,展示refs)
撤回操作
svn中的revert
-
對(duì)工作區(qū)
也就把工作區(qū)的變動(dòng)回復(fù)到head的狀態(tài)票彪,采用以下代碼:
git reset --hard HEAD~0
(解釋--hard --soft的區(qū)別),把目標(biāo)目錄變成某個(gè)版本的樣子不狮, ~0表示版本 -
對(duì)某個(gè)文件
git reset --hard HEAD
git reset
把當(dāng)前head以及HEAD指向某個(gè)版本降铸,把后面的版本摒棄。(摒棄不意味著消失摇零,git的一切提交都不會(huì)消失推掸,只是變成了難以再獲取到的孤魂野鬼)。HEAD~1代表上一個(gè)版本。
注意:
當(dāng)HEAD是合并而來(lái)的版本的時(shí)候谅畅,HEAD~1代表當(dāng)前分支的父節(jié)點(diǎn)登渣,HEAD^1代表另一分支的父節(jié)點(diǎn)
黃金法則 GOLDEN RULE
不要在公共的分支上(已經(jīng)在服務(wù)器上存在的分支)進(jìn)行reset操作。
svn中的update to revision
svn中我們使用這種方法來(lái)檢出過(guò)去的代碼毡泻,在git中使用:
git checkout <commit>
就可以把工作區(qū)checkout到這個(gè)狀態(tài)胜茧。
注意:此時(shí)處于一個(gè)dettached head狀態(tài)。
非大陸版本翻譯為“斷頭狀態(tài)”仇味。HEAD一般是指向refs/heads中的某個(gè)文件(這些文件又會(huì)指向某個(gè)版本)呻顽,成為attched head狀態(tài),而當(dāng)checkout為某個(gè)版本的時(shí)候丹墨,HEAD會(huì)顯示為某個(gè)版本號(hào)芬位。成為斷頭。
當(dāng)你需要在checkout出來(lái)的版本工作
斷頭狀態(tài)下所有的提交均不屬于任何分支带到,屬于無(wú)效提交昧碉。當(dāng)需要在這個(gè)狀態(tài)下工作時(shí),最好建立一個(gè)新的分支來(lái)工作揽惹,最后再合并到目標(biāo)分支被饿。
git revert
同樣用于撤銷操作,需要和svn中作出區(qū)分搪搏。這是一個(gè)安全的操作狭握,可以用于已經(jīng)共享的分支。具體操作相當(dāng)于找到某個(gè)版本的changeset疯溺,逆之论颅,然后作為一次新的commit提交。相當(dāng)于幫我們手工做了一次改錯(cuò)囱嫩。
使用方法git revert <commit>
恃疯。
必學(xué)時(shí)光回溯大法
任何想好好實(shí)用git的人都必須學(xué)會(huì)這一節(jié)。
當(dāng)我們執(zhí)行reset之后墨闲,hard模式下三個(gè)tree都會(huì)退回到你的目標(biāo)版本今妄,此時(shí)執(zhí)行git log
,是看不到被reset掉后面的版本的鸳碧,就好像什么都沒(méi)發(fā)生過(guò)一樣盾鳞。這樣子當(dāng)自己手賤不小心reset掉自己需要的代碼了,豈不是要捶胸頓足瞻离?
不用怕腾仅,之前就講過(guò),git是一個(gè)永遠(yuǎn)都不會(huì)丟失提交的vcs套利,只要是提交過(guò)的推励,都能找回鹤耍。這個(gè)時(shí)候需要一個(gè)神器了,那就是reflog吹艇。讓我們輸入reflog,可以看到如下的東西:
$git reflog
c75dc97 (HEAD -> nb) HEAD@{0}: reset: moving to HEAD~1
c1998f3 (master) HEAD@{1}: checkout: moving from master to nb
c1998f3 (master) HEAD@{2}: commit: add the first line
c75dc97 (HEAD -> nb) HEAD@{3}: commit (initial): commit first
可以看到最上面reset了一個(gè)版本“悍鳎現(xiàn)在我們突然想要前面的某個(gè)版本了受神,直接執(zhí)行
git checkout HEAD@{n}
就可回到任意版本,復(fù)制出你要的文件然后回到最新版本復(fù)制回去格侯,或者新開(kāi)分支工作都可以, whatever you like鼻听。
令人激動(dòng)的分支操作
基于版本的分支。
查看
查看分支联四,帶星號(hào)的為當(dāng)前所處分支git branch
查看遠(yuǎn)端分支git branch -r
切換分支
git checkout <branch>
實(shí)質(zhì)上是改變了HEAD的指向撑碴。
新建分支
git branch <branch>
git checkout -r <branch>
新建分支并切換過(guò)去
刪除分支
git branch -d <branch>
安全刪除分支,必須在被合并之后才允許刪除
git branch -D <branch>
強(qiáng)行刪除分支
merge
把一堆操作集合起來(lái)作為一個(gè)merge commit朝墩,會(huì)自動(dòng)處理好歷史醉拓。
操作步驟:
- 切換到當(dāng)前分支
git checkout <master-branch>
- 合并
git merge <feature-branch>
rebase
換基。同樣需要尊崇黃金法則收苏,不能更改公共分支亿卤。
直接把整條分支的起點(diǎn)挪到源分支的head處。在公共分支使用容易引起冗余changeset鹿霸。(選擇性講解排吴,看時(shí)間)
rebase和merge的區(qū)別
...
遠(yuǎn)端操作
存放在refs/remotes文件夾下
新建立遠(yuǎn)端
git remote add <remote-name> <remote-url>
一般起名字為origin,跟著git的標(biāo)準(zhǔn)寫(xiě)懦鼠。
刪除遠(yuǎn)端
git remote remove <remote-name>
rename
就叫rename git remote rename <old> <new>
pull
相當(dāng)于fetch + merge/rebase
git pull <remote-name>
當(dāng)加上--rebase標(biāo)志時(shí)表示使用rebase钻哩,一般由于是公共分支,不要這么搞比較好肛冶。
push
把所有的commit提交到服務(wù)器
git push <remote-name> [--force]
別名
允許我們自定義別名街氢,比如使用decompress來(lái)代表解壓操作,那么
git config --global alias.decompress "cat-file -p"
既可睦袖。