Git安裝
- 地址:https://git-scm.com/downloads
- 下載對應平臺的git版本安裝即可
Git配置
配置快捷命令
- 在用戶根目錄下(如C:/user/Administrator)新建配置文件命名為.gitconfig
- 將以下內容寫入文件
[user]
email = xxx(郵箱如:foxleezh@gmail.com)
name = xxx(名字如:foxleezh)
[alias]
st = status
ci = commit
br = branch
co = checkout
glog = log --pretty=oneline
pus = push
pul = !git pull --rebase && git submodule update --init --recursive
lg = log --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit
[merge]
tool = vim
[core]
packedGitLimit = 512m
packedGitWindowSize = 512m
[pack]
deltaCacheSize = 2047m
packSizeLimit = 2047m
windowMemory = 2047m
配置ssh
- 在命令行輸入
ssh-keygen -t rsa
- 在用戶目錄(如C:/user/Administrator)打開.ssh文件夾,查看id_rsa.pub文件,將密鑰拷貝到服務器密鑰庫
配置忽略文件
- 將.gitignore文件放置到項目根目錄下
# OSX
*.DS_Store
# Gradle files
build/
build_out/
obj/
.gradle/
*/build/
captures/
gradle/
# IDEA
*.iml
.idea/.name
.idea/encodings.xml
.idea/inspectionProfiles/Project_Default.xml
.idea/inspectionProfiles/profiles_settings.xml
.idea/misc.xml
.idea/modules.xml
.idea/scopes/scope_settings.xml
.idea/vcs.xml
.idea/workspace.xml
.idea/libraries
.idea/runConfigurations.xml
.idea/compiler.xml
.idea/copyright/profiles_settings.xml
.idea/gradle.xml
.idea/
# Built application files
*.ap_
# Files for the Dalvik VM
*.dex
# Java class files
*.class
# Local configuration file (sdk path, etc)
local.properties
# Log Files
*.log
# Special
gradle.properties
- 凡是在列表中的文件(*表示所有)都將被git忽略,對這些文件的任何改動,git都不會追蹤
- 但是有時我們只想追蹤某幾個文件,其它都忽略,可以如下配置,!后面的內容為追蹤的文件
/*
!.gitignore
!README.md
Git使用
- 命令行使用(windows打開git bash , mac 打開終端)
- Git bash是命令行工具,內部使用linux指令集(linux使用文件另附)
- 更多linux命令http://www.php100.com/html/webkaifa/Linux/2009/1106/3485.html
一.準備工作
- 新建倉庫(進入到項目的根目錄下)
git init
- 添加忽略規則,將.gitignore文件放置到根目錄下
- 添加文件,將需要管理的文件加入到根目錄下
二.代碼管理
- 查看狀態
git st
紅色表示已修改未保存到緩存區,綠色表示已保存到緩存區
Git有三個狀態,一是修改未保存到緩存,二是保存到緩存,三是提交到版本庫
我們可以對比著word文檔來學習,狀態一就相當于你在word中修改了一些東西,但是沒有按ctrl+s鍵保存起來,狀態二就是你修改了東西后按了ctrl+s,暫時存起來了,狀態三就是點擊了另存為,將它另外存放起來了
- 保存到緩存區
git add 文件路徑(添加單個文件到緩存)
一開始修改了homepage和loading兩個文件,git st后顯示紅色
使用git add后,將homepage加入到緩存區
git st后,發現homepage變為綠色
git add -u(添加所有修改到緩存)
一開始修改了homepage和loading兩個文件,git st后顯示紅色
使用git add -u后,將homepage和loading一起加入到緩存區
git st后,發現homepage和loading變為綠色
git add . (添加所有文件到緩存,包括新建的文件)
此用法與git add -u類似,區別在于,git add -u只能將修改的文件加入緩存,如果該文件是新建的,要使用git add ., 這個“.”符號表示所有
- 撤銷緩存區的文件
git reset 文件路徑(撤銷單個文件)
首先git st后發現,有兩個已經加入到緩存區的homepage和loading文件
使用git reset homepage后,將homepage文件撤銷
git st后發現,homepage變為紅色
git reset(撤銷所有緩存區的文件)
首先git st后發現,有兩個已經加入到緩存區的homepage和loading文件
使用git reset后,將所有文件撤銷
git st后發現,homepage和loading都變為紅色
- 撤銷修改
git co 文件路徑(撤銷單個文件的修改)
首先使用git st,發現有homepage和loading兩個文件被修改
使用git co homepage,撤銷homepage的修改
git st后發現homepage文件不見了,查看原代碼,代碼中的修改也沒有了
git reset --hard (撤銷所有文件的修改)
首先使用git st,發現有homepage和loading兩個文件被修改
使用git reset --hard,撤銷所有的修改
git st后發現homepage和loading文件不見了,顯示nothing to commit,working directory clean, 這表示當前沒有任何的修改
- 查看修改的內容
git diff 文件路徑(查看單個文件修改)
首先使用git st,有兩個文件Homepage,loading被修改
使用git diff homepage,可以看到哪些被修改了,按箭頭上下可以翻動,”-”號表示刪除(紅色顯示),”+”號表示添加(紅色顯示)
查看完成后輸入q,即可退出查看
要查看所有修改直接用git diff
git diff --cached (查看處于緩存區的修改)
首先使用git st,有兩個文件Homepage,loading被加入到緩存區
使用git diff homepage,可以看到哪些被修改了,按箭頭上下可以翻動,”-”號表示刪除(紅色顯示),”+”號表示添加(紅色顯示)
查看完成后輸入q,即可退出查看
要查看所有修改直接用git diff --cached
- 將緩存區的內容提交到版本庫
git ci -m “我修改了什么”
首先git st,發現有兩個文件homepage和loading加入到緩存區
使用git ci -m “注釋”,將緩存區的內容提交到版本庫,這里注釋是隨便寫的,用于提示該commit修改了一些什么內容
git st后發現,緩存區中的內容不見了,這是因為已經提交到版本庫中了
- 查看版本庫中的內容
git log
git log后發現有兩個提交,“我修改了什么”是剛剛提交的commit,下面來分析下:
commit ac76744b1843665d0c6cf1add7cf758bc824c89a (這行是一個md5值,用來唯一標識commit的)
Author: foxleezh foxleezh@gmail.com (這行是說明該commit是誰提交的)
Date: Fri Jul 10 10:02:16 2015 +0800 (提交的時間)
我修改了什么 (之前我們寫的注釋)
- 查看某個提交中修改的內容
git show commit號
git show ac76744b, 這個ac76744b就是之前git log時對應的md5值,可以只取前6位
查看完成用q退出
我們回顧一下已講的內容,一般來說使用流程都是
- 修改了一些內容,用git st看看狀態
- git diff看看修改了哪些內容
- 確認無誤后,將需要提交的內容git add加入到緩存區
- git ci -m 加入到版本庫中,這里說一下,平常我們都用git ci -m新建一個commit,其實通常我們不用新建commit,而是用git ci --amend追加的方式
這里我們修改了loading中的內容,然后git add -u 加入到緩存區,因為我們只是修改了很少的內容,不需要重新提交commit,所以使用git ci --amend追加到之前的commit,這時會讓我們修改注釋內容
這是一個vim的編輯器,之前linux中有講,按i進入編輯模式,箭頭移動光標就可以修改注釋,修改好后,按ESC進入一般模式,按:進入命令模式,輸入wq,保存退出
git log后發現沒有新建commit,只是追加到了之前的commit
我們在使用的過程中可能要回到某一個提交,這時可以使用git reset命令,這個命令可以帶參數,--mixed(回到修改未保存狀態),--soft(回到緩存區狀態),--hard(刪除所有修改),默認是--mixed
先講講--hard,這個好理解,就是把這個commit之后的所有修改都刪除
這里有四個commit
我們先使用git reset --hard ,將“我修改了名字”之后的所有修改的刪除
git st后發現,沒有任何修改
git log后,已經回到”我修改了名字”的commit
下面我們試試git reset --mixed或者git reset
git log我們會發現--mixed和--hard都回到了“我修改了名字”的版本,區別在于git st后--mixed將“測試reset1”和“測試reset2”中修改的內容保留下來了,這樣好處在于,我們有時回到某一個commit不是要刪除所有的修改,而是只想改變某一些東西,這時我們把需要改的地方改掉后,再重新提交一個commit,這樣會方便很多
最后我們試試git reset --soft
這個跟git reset --mixed差不多,只是它是把之后的修改放入了緩存區
三.分支操作
之前我們的操作都是同一個分支上的操作,現在我們引入分支的概念
- 查看分支
git br
git默認都會有一個分支叫master,這個分支叫主分支,一般來說我們提交代碼的時候是用這個分支來提交,但是實質上它跟普通的分支沒有什么區別
為什么我們要引入分支,svn也有分支的概念,但是基本是在服務器端,我們本地基本是在一個分支上修改內容的,然后commit,有時我們改一個東西A可能需要很長時間,當還沒有改完卻突然要修改另外一個東西B,而且A因為沒有改完不能合并到版本庫,這時svn就有點乏力了,我們可能要把之前沒改完的東西A刪除掉,然后再來改接下來的B。
git因為是分布式的,不管是服務器端還是本地,都可以存在很多分支,這樣就方便我們利用分支很好地管理代碼,當我們修改任務A的時候,我們可以在分支A上修改,分支A在master的基礎上新建而來,當我們還沒有處理完A就要處理B時,我們可以新建另一個分支B,也是在master的基礎上新建而來,這樣當我們處理完B,提交后,可以回到A,繼續我們之前的開發,當我們開發完A,要提交的時候,我們把B的內容整合進來,這個涉及到分支合并,我們之后再講
- 新建分支
git co -b TEST //新建名為TEST的分支,當前的分支會以綠色顯示
當我們新建分支時,是從當前分支的基礎上新建的,新建的分支保留了當前分支所有的修改,所以新建分支相當于對當前分支的一份拷貝,而不是一個空的分支
- 切換分支
git co master //切換到master分支
- 刪除分支
git br -D TEST //D大寫,表示強制刪除
-
分支合并
講合并,我們就回到之前那個例子,我們處理A任務和B任務都新建一個分支分別為TESTA和TESTB,這兩個分支都是在master的基礎上新建過來的
這里有三個分支,分別是master,TESTA,TESTB
主分支master有兩個提交
git co TESTA切換到TESTA,上面有三個提交,在master基礎上多了一個“測試A”的提交
git co TESTB切換到TESTB,上面有三個提交,在master基礎上多了一個“修改B”的提交
現在我們需要把A和B合并到一起
首先切換到TESTA分支,然后使用git rebase TESTB命令,將TESTB合并到TESTA前面
一般來說,如果兩個分支沒有沖突的話,合并就完成了,像上圖有沖突就需要解決沖突
git st后發現,TESTA和TESTB都修改了loading文件
git diff loading后,查看具體的沖突內容,git用特殊的符號標記沖突,<<<<<< HEAD到=======之前是你要合并的分支對當前文件的修改,因為現在我是要把TESTB合并到TESTA,所以HEAD就代表TESTB的修改,也就是“我是用來追加的B”是TESTB的修改,然后======與>>>>>>之前的內容是TESTA的修改,也就是“我是用來追加的A”這句話
現在我們要做的就是確認好是保留A的內容,還是保留B的內容,還是A和B的內容都保留,我們修改可以用linux的vim工具來修改,也可以直接在Android studio或者xcode中修改,修改時先將<<<<<,======這些特殊標記符號去掉,然后再進行修改
修改完成后,git add -u 將修改的內容加入到緩存區
然后git rebase --continue,繼續rebase操作
如果要放棄合并,使用git rebase --abort
合并完成后git log,我們可以看到,TESTB的修改“修改B”已經合并進TESTA了,這時TESTA分支中就包含了A和B的修改
四.與遠程服務器交互
- 生成rsa密鑰
ssh-keygen -t rsa
查看id_rsa.pub文件,將密鑰拷貝到服務器密鑰庫
- 從遠程復制倉庫
git clone 服務器倉庫地址
一般來說是新建一個空目錄,然后去克隆服務器的git倉庫
- 在服務器添加倉庫
1.新建本地倉庫
git init
2.添加遠程倉庫地址
git remote add origin ssh://****@****:29418/foxleezh/test.git
3.提交遠程倉庫
git push origin master
4.切換到遠程分支
git br -r 查看遠程分支
git co 切換到某一個遠程分支
5.刪除遠程分支
git push origin :branch
6.拉取服務器分支并切換到臨時分支
git fetch origin branchname && git co FETCH_HEAD
如:
git fetch origin GIT && git co FETCH_HEAD
7.拉取服務器分支并合并到master
git pull
pull命令相當于fetch命令加上merge命令,將服務器master分支的內容拉下來并合并到本地master
git pull --rebase
以rebase形式拉取,相當于fetch命令加上rebase命令
如果是pull其他分支,加上分支名
git pull origin branchA
8.向服務器提交分支
git push
如果是push其他分支,加上分支名
git pull origin branchA
9.常見錯誤
- unable to rewind rpc post data - try increasing http.postBuffer
git config http.postBuffer 524288000
- 高版本不支持ssl
Host www.xxx.com(改成服務器地址)
HostkeyAlgorithms ssh-dss
五.子模組
- 新建子模組
1.新建父項目、子項目并上傳服務器
2.克隆父項目、子項目到不同目錄
git clone ssh://<username>@<hostname>:29418/project-1.git
git clone ssh://<username>@<hostname>:29418/lib1.git
git clone ssh://<username>@<hostname>:29418/lib2.git
3.將子項目變為父項目的子模組
git submodule add ssh://<username>@<hostname>:29418/lib1.git libs/lib1(這里目錄可以自由更改)
git submodule add ssh://<username>@<hostname>:29418/lib2.git libs/lib2
4.將父項目修改的修改提交服務器
git add -u
git push
至此,子模組新建完成
- 修改子模組
1.進入子模組目錄提交并上傳
git add -u
git push
2.進入父項目提交并上傳
git add -u
git push
- 克隆子模組
1.克隆父項目
git clone --recursive ssh://<username>@<hostname>:29418/project-1.git
2.切換子項目分支
到子目錄下(此時分支處于游離狀態)
git co -b newBranch
- 更新子模組
1.在父目錄下更新
git pull
git submodule update
2.切換子項目分支
此時分支處于游離狀態
git co -b newBranch
- 刪除子模塊(分4步走)
1.根據路徑刪除子模塊的記錄
$ git rm --cached [path]
2.編輯“.gitmodules”文件,將子模塊的相關配置節點刪除掉
清理子模塊配置
3.編輯“ .git/config”文件,將子模塊的相關配置節點刪除掉
清理子模塊配置
4.手動刪除子模塊殘留的目錄
清理臟文件
六、其他
- Git找回commit
git reflog
-
開發流程(以master為例)
- 在master的基礎上新建一個分支進行修改
git co -b newbranch
- 在新的newbranch上改好代碼后commit
git add -u
git ci -m "newbranch的修改"
- 切換到master上拉取最新代碼,防止別人上傳了代碼自己卻沒有更新
git co master
git pull origin master
- 如果服務器有代碼更新,切換回newbranch合并服務器新增代碼(如果沒有更新,直接執行第5步)
git co newbranch
git rebase master
- 切換到master,合并newbranch代碼
git co master
git rebase newbranch
- 提交代碼到服務器
git push origin master
- 在master的基礎上新建一個分支進行修改
-
有關git rebase的常識
- 對于rebase的順序
比如 上例中newbranch和master兩個分支的合并
一開始兩分支commit都是1,2,3
后來newbranch提交了一個4,commit就是1,2,3,4的順序
而master拉取服務器更新了5,commit就是1,2,3,5的順序
這時我們切換到newbranch,去rebase master,即git rebase master
rebase后的順序是1,2,3,5,4
如果我們當初是切換到master,去rebase newbranch
rebase后的順序是1,2,3,4,5
這里的法則就是,去rebase哪個分支,就把哪個分支塞在下面
- 對于rebase沖突的解決
當我們rebase后,看見有沖突,git st后可以看到沖突的文件
我們通過Android studio找到沖突的文件,去搜索=====或者<<<<<<這些特殊標記就會找到沖突的代碼
修改沖突的代碼為你想要的代碼后,記得將=====,<<<<<這些特殊符號去掉
修改好后git add -u,將修改的代碼提交到緩沖區
git rebase --continue繼續rebase,這樣就將沖突解決了
如果rebase過程中想取消,git rebase --abort
- 能過rebase刪除某幾個commit
比如newbranch上的commit為1,2,3,4
這時我想將中間的2和3去掉,變為1,4
我們首先要將2和3的commit號記下,比如是commit2,commit3
然后git rebase --onto commit2空格commit3(commit2后面的是前一個的意思,這個符號在鍵盤的數字6上面)
其實可以是git rebase --onto commit1空格commit3(因為commit2^就是commit1)
- 對于rebase的順序
-
一些Linux常用命令
tab 補全命令
ctrl+c 停止執行
- 文件管理
pwd 打印當前目錄
cd 進入某個目錄
cd /home/develop 進入絕對路徑
cd eclipse 進入相對路徑
cd ../ 返回上一級目錄touch [file name]打開或創建一個文件
mkdir -p [dir name] 創建一個目錄 -p為強制創建
rm -r [file name/dir name] 刪除一個文件或目錄
ls -al 列出所有文件(包括隱藏文件)的詳細信息
-d 只列出該目錄的信息cp -rd [目標文件] [目的文件] 復制文件
-r是允許目錄cp
-d是在拷貝軟連接時只拷貝軟連接,如果不加則會把原文件一起拷過去
cp -rd test.txt dir/test.txtmv -i [目標文件] [目的文件] 移動文件
-i是詢問是否覆蓋同名文件,如果[目標文件][目的文件]相同,那就是重命名find [dn] [參數]
如:find $HOME -name 'foxlee' -o -type f -o -size +20M
-atime +n :訪問或執行時間大于n天的文件
-ctime +n :寫入、更改inode屬性(例如更改所有者、權限或者連接)時間大于n天的文件
-mtime +n :寫入時間大于n天的文件
文件的 Access time,atime 是在讀取文件或者執行文件時更改的。
文件的 Modified time,mtime 是在寫入文件時隨文件內容的更改而更改的。
文件的 Create time,ctime 是在寫入文件、更改所有者、權限或鏈接設置時隨 Inode 的內容更改而更改的。
因此,更改文件的內容即會更改 mtime 和 ctime,
但是文件的 ctime 可能會在 mtime
未發生任何變化時更改,例如,更改了文件的權限,但是文件內容沒有變化。
這里講一下ls中顯示的時間
ls -lc filename 列出文件的 ctime
ls -lu filename 列出文件的 atime
ls -l filename 列出文件的 mtime
繼續講find的參數
-name 'filename' 直接查找該文件名的文件(注意加引號)
-type type :通過文件類型查找 type 包含了 f, b, c, d, l, s 等等
d 表示該文件為目錄;
f 表示該文件為普通文件;
b 表示該文件為塊設備文件,比如磁盤分區
l 表示該文件為連接文件(linux file),上邊提到的軟連接即為該類型;
c 表示該文件為串行端口設備,例如鍵盤、鼠標。
s 表示該文件為套接字文件(socket),用于進程間通信。
- 文件查看與編輯
vim [fn] 編輯文件 有三種模式(一般模式,編輯模式,命令模式),可以自由切換
一般模式下移動光標(esc回到一般模式)
箭頭上下左右一般模式下查找與替換
/word 向光標之后尋找一個字符串名為word的字符串,當找到第一個word后,按”n”繼續搜后一個,"N"前一個一般模式下刪除、復制粘貼
dd 刪除光標所在的那一行
yy 復制光標所在的那行
p,P p復制的數據從光標下一行粘貼,P則從光標上一行粘貼
u 還原過去的操作進入編輯模式(按i進入)
i 在當前字符前插入字符命令模式(按:進入)
:q! 不管編輯或未編輯都不保存退出
:wq 保存,退出
:e! 將文檔還原成最原始狀態
:set nu 在每行的行首顯示行號
:set nonu 取消行號
- 文件管理