Git详解
前言
Git是目前世界上最先进的分布式版本控制系统。本文从头详细地介绍了Git的各种用法。
配置本机用户和邮箱
λ git config --global user.name 名字
λ git config --global user.email 邮箱
注意:git config
的--global
参数代表本机上所有git仓库都用这个配置。
若想为某个仓库配置其它的用户名和邮箱:
λ git config -user.name 名字
λ git config ser.email 邮箱
查看全局用户名和邮箱:
λ git config --global user.name
λ git config --global user.email
查看某仓库用户名和邮箱同理,上述语句去掉--global
就可以。
创建仓库
将当前目录编程Git可以管理的仓库:
λ git init
Initialized empty Git repository in C:/Users/hwx/Desktop/learngit/.git/
C:/Users/hwx/Desktop/learngit
是我的目录,.git
目录用来跟踪管理版本库,不用管它。
将文件添加到版本库
注意:所有版本控制系统只能跟踪文本文件的改动,可以告诉你每次改动的细节。但是不能跟踪图片、视频这些二进制文件的变化,只能知道文件大小的变化。
下面我们添加一个readme.txt到仓库,分两步:
1.用命令git add
将文件添加到暂存区:
λ git add readme.txt
该命令执行成功不会有任何显示,可以同时add多个文件,中间用空格隔开。
2.用命令git commit
将文件从暂存区提交到仓库:
λ git commit -m "add a readme text"
[master (root-commit) 6fd4dfc] add a readme text
1 file changed, 2 insertions(+)
create mode 100644 readme.txt
-m
后面是本次提交的说明。
注意:git commit
只会提交暂存区中的修改,没放进暂存区的不会提交。
git status
查看仓库状态。
1.仓库中有文件没add
λ git status
On branch master
Untracked files:
(use "git add <file>..." to include in what will be committed)
.1.txt.swp
nothing added to commit but untracked files present (use "git add" to track)
2.仓库中有文件修改过了,但是没add
λ 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: readme.txt
no changes added to commit (use "git add" and/or "git commit -a")
3.仓库中有文件add了,但是没有commit
λ git status
On branch master
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
modified: readme.txt
4.仓库该add的都add了,该commit的都commit了
λ git status
On branch master
nothing to commit, working tree clean
git diff
工作区是目录,仓库是版本库。git diff
比较的是工作区文件与暂存区文件(上次git add 的内容)的区别git diff --cached
比较的是暂存区的文件与仓库文件(上次git commit 的内容)的区别git diff HEAD --
比较的是工作区文件和仓库文件
git log
查看仓库历史:
λ git log
commit e1f285812d2202a32fed025f309fb6e7a68fde49 (HEAD -> master)
Author: Wenxing Hu <[email protected]>
Date: Sat Dec 22 14:22:32 2018 +0800
readme add forth line
commit 859c43221f414215c34c95004ab3930c407caee6
Author: Wenxing Hu <[email protected]>
Date: Sat Dec 22 14:14:04 2018 +0800
readme add 3 line
commit 6fd4dfc32c1ba2bec1fe5e61b85b721c5ed62d2c
Author: Wenxing Hu <[email protected]>
Date: Sat Dec 22 13:57:17 2018 +0800
add a readme text
从下到上是按照时间排序的每次commit的信息。
信息太多了?加上--pretty=oneline
参数:
λ git log --pretty=oneline
e1f285812d2202a32fed025f309fb6e7a68fde49 (HEAD -> master) readme add forth line
859c43221f414215c34c95004ab3930c407caee6 readme add 3 line
6fd4dfc32c1ba2bec1fe5e61b85b721c5ed62d2c add a readme text
每行前面的一大串是commit id。git log --oneline
可以只显示前7位id。
git reset
回退到某一个版本HEAD
是个指针,代表当前的版本。上个版本是HEAD^
,上上个是HEAD^^
,往上n个版本可以写成HEAD~n
。
λ git reset --hard HEAD~
HEAD is now at 859c432 readme add 3 line
注意:执行git reset --hard HEAD^
可能会出来个more?
这是因为命令行中^是换行符,所以还是用HEAD~1
吧。
也可以根据commit id来进行版本变换:
git reset --hard e1f2
HEAD is now at e1f2858 readme add forth line
这里commit id输入四个字符就可以了。
注意:git log
只能看到HEAD指向的版本及之前的版本。
版本变换多了,弄晕了,不要紧,命令git log --reflog
用来查看所有版本。还有命令git reflog
可以查看每次执行的命令。
撤销修改
1.工作区的文件弄坏了,git checkout -- 文件名
这条命令可以使它回到最新的add或commit时的状态,俗称一键还原。
2.工作区的文件弄坏了,还add到了暂存区,用命令git reset HEAD 文件名
,可以将其方会工作区,这样就回到了1的情况,再执行1就可以了。
删除文件
先git rm 文件名
,再git commit
。
λ git rm test.txt
rm 'test.txt'
λ git commit -m "delete test.txt"
[master ee28494] delete test.txt
1 file changed, 0 insertions(+), 0 deletions(-)
delete mode 100644 test.txt
远程仓库
远程仓库这里以GayHub为例,当然你也可以自己搭建一个服务器运行Git。
1.将本地仓库和远程仓库通过SSH连接。
λ ssh-****** -t rsa -C "你的邮箱"
然后根据提示一路回车。。。
运行成功后,可以在用户主目录里找到.ssh目录,里面有id_rsa
和id_rsa.pub
两个文件,这两个就是SSHKey的秘钥对,id_rsa
是私钥,不能泄露出去,id_rsa.pub
是公钥,可以放心地告诉任何人。
然后在GitHub中添加SSH key,把公钥添加进去就ok了。
2.关联本地仓库和远程仓库
首先在GitHub中新建一个仓库(Repository):
按它的提示,在本地仓库执行命令:
git remote add [email protected]:649453932/git-test.git
将本地仓库推送到远程仓库的命令:
git push -u origin master
其中-u
只在第一次推送时加,origin代表远程仓库,注意本地仓库只有commit了的文件才会推送到远程仓库。
之后每次推送时**git push origin 分支名
**,你可以推送本地的mastet到远程仓库,当然也可以选择本地的其他分支推送。注意:远程仓库也可以有好多分支。
移除关联的远程仓库:
git remote rm origin
3.从远程仓库克隆
git clone [email protected]:649453932/git-test.git
可以随便从GitHub中clone仓库,clone回来就成了你的一个本地库,但保留了该仓库之前的各种记录。
分支管理
刚开始,只有一个分支,名为master,可以再创建分支,分支之间平时互不影响,可以并行开发。
查看所有分支:git branch
,当前分支前会有个*
创建分支:git branch 名字
切换到分支:git checkout 名字
创建并切换到分支:git checkout -b 名字
合并指定分支到当前分支:git merge 名字
删除分支:git branch -d 名字
冲突处理
若master分支和另外一个分支同时对一个文件做了修改,那就不能merge了。
这就需要我们手动解决了:
λ cat readme.txt
This is a readme text.
This is second line.
This is third line.
forth
fifth
sixth
seventh
eighth_master_dev1
<<<<<<< HEAD
master !!!
=======
dev2 !!!
>>>>>>> dev2
Git用<<<<<<<
,=======
,>>>>>>>
标记出不同分支的内容我们把这些符号删掉,改成我们想要的内容。再在master分支上add和commit,主分支就改好了,另外一个分支现在就可以merge了。
图形化分支合并情况
git log --graph
命令可以查看分支合并情况:
λ git log --graph --pretty=oneline --abbrev-commit
* 99fdeac (HEAD -> dev2, master) conflict fixed!
|\
| * 47c854e ADD eighth
* | 53ba977 ADD eighth_maser
|/
* e555cd8 branch test
* ee28494 (origin/master) delete test.txt
* 0ec907e add test.txt
* cd95b35 fidth line
* 6fd4dfc add a readme text
分支merge技巧
通常,合并分支merge
时,如果可能,Git会用Fast forward
模式,但这种模式下,删除分支后,会丢掉分支信息。
使用--no-ff
可以禁用Fast forward
,merge时会生成新的commit,就可以从log看到分支。git merge --no-ff -m "merge with no-ff" 要merge的分支名
λ git merge --no-ff -m "merge noff" dev7
Merge made by the 'recursive' strategy.
readme.txt | 1 +
1 file changed, 1 insertion(+)
然后我们看log,dev6是 Fast forwar 模式进行merge的,而dev7是--no-ff模式进行merge的:
λ git log --graph --pretty=oneline --abbrev-commit
* 5571146 (HEAD -> master) merge noff
|\
| * dbc506e (dev7) dev7
|/
* 2122b61 (dev6) dev6
|
...
git stash
该命令可以将工作现场
存储起来,之后可以再恢复。用于临时处理其它分支的事务,处理完再回来将自己存储的工作现场恢复。
λ git stash
Saved working directory and index state WIP on dev6: 2122b61 dev6
用git stash
可以查看存储的工作现场。git stash apply
恢复现场,但是之后还需要用git stash drop
来删除存储的。可以直接用git stash pop
来恢复现场并删除存储。
注意:只有被add过的文件才会被git stash存储,注意是add 过,只要曾经add过就行。
删除分支
git branch -d dev1
λ git branch -d dev1
error: The branch 'dev1' is not fully merged.
If you are sure you want to delete it, run 'git branch -D dev1'.
若该分支没有被合并,删除就会丢失该分支上的修改,强制删除命令:git branch -D 分支名
。
多人协作
git remote -v
:显示详细信息
λ git remote -v
origin [email protected]:649453932/learngit.git (fetch)
origin [email protected]:649453932/learngit.git (push)
上面显示了可以抓取和推送的origin的地址。如果没有推送权限,就看不到push的地址。
从本地推送时用下面的命令,将本地分支推送到远程仓库的分支:
git push origin 分支名
若两个人同时处理一个远程分支,一个人推送了,另外一个人再推送就会失败,得先用git pull
将最新的提交从origin/分支名
抓下来与本地合并,再推送。
也有可能两人修改了同一个文件,pull下来有冲突,需要手动解决,解决方式见前面的冲突处理。
忽略特殊文件
建一个.gitignore文件。
里面这样写:
# 这是注释
这里是你想忽略的文件
*可以代指任何字符串
...
这样每次git status
就不会提示这些文件了。