由于今年转向Framework开发了,进来发现公司内部使用的都是Git作为版本控制,来之前使用的也不多,进来后也使用了将近半年了,都会用了,但命令还是不太容易记住,所以在这里做一个记录,毕竟好记性不如烂笔头。
注:以下内容从博文http://www.liaoxuefeng.com/wiki/0013739516305929606dd18361248578c67b8067c8c017b000/学习总结而来。在此,感谢原作者。
Git是一个开源的分布式版本控制系统,可以有效、高速的处理或大或小的项目版本管理。Git起初是由Linus Torvalds开发的。
目前版本控制系统主要有两种,分别是集中式版本控制系统(如CVS和SVN)和分布式版本控制系统(如Git)。
集中式版本控制系统:有一个中央服务器,所有代码库都只保存在其中,工作时都用的自己电脑,从服务器获取,提交时最终都要汇总到中心服务器。总之,服务器挂了,所有库都完蛋了。而且必须要联网的情况下才能使用,上传速度也慢。
分布式版本控制系统:分布式版本控制系统没有中央服务器,每个人的电脑上都是一个完整的版本库,只要交换对方的修改就行,把各自的修改推送给对方。而且分布式版本控制系统也有一台充当“中央服务器”的电脑,只是用来交换修改之用。
区别:集中式需要联网,分布式不需要;集中式上传速度慢,分布式快;集中式必须要有中心节点才能干活,分布式可以不需要;集中式不需要初始化很多东西就能干活,而分布式则要拷贝整个历史记录。
一、安装和创建版本库
1、安装和配置
三大操作系统平台都支持,安装很简单,然后主要是安装后的配置。
$ git config --global user.name "Your Name"
$ git config --global user.email "email@example.com"
git config命令的–global参数,表示你这台机器上所有的Git仓库都会使用这个配置,当然也可以对某个仓库指定不同的用户名和Email地址。
2、创建版本库
版本库也即(仓库)repository,也可理解为一个目录。
第一步:Linux下创建目录:
yjq@ubuntu:~$ mkdir learn_android
yjq@ubuntu:~$ cd learn_android/
yjq@ubuntu:~/learn_android$ pwd
/home/yjq/learn_android
第二步:git init将目录变成Git可以管理的仓库:
yjq@ubuntu:~/learn_android$ git init
Initialized empty Git repository in /home/yjq/learn_android/.git/
执行ll命令可看到多了一个.git文件夹
yjq@ubuntu:~/learn_android$ ll
total 12
drwxr-xr-x 3 yjq root 4096 Aug 26 17:06 ./
drwxr-xr-x 10 yjq root 4096 Aug 26 16:57 ../
drwxr-xr-x 7 yjq root 4096 Aug 26 17:06 .git/
第三步:添加文件到Git仓库里:
新建文件readme.txt:
yjq@ubuntu:~/learn_android$ touch readme.txt
yjq@ubuntu:~/learn_android$ ls
readme.txt
用git来add和commit文件:
yjq@ubuntu:~/learn_android$ git add readme.txt
yjq@ubuntu:~/learn_android$ git commit -m "add a new file"
[master (root-commit) 133b2fb] add a new file
0 files changed
create mode 100644 readme.txt
二、版本管理
1、版本修改查看
往readme.txt中添加文本blablabllblablalblbal,然后使用git status查看:
yjq@ubuntu:~/learn_android$ git status
yjq@ubuntu:~/learn_android$ 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")
git diff查看文件修改内容:
yjq@ubuntu:~/learn_android$ git diff readme.txt
diff --git a/readme.txt b/readme.txt
old mode 100644
new mode 100755
index e69de29..6741507
--- a/readme.txt
+++ b/readme.txt
@@ -0,0 +1 @@
+blablabllblablalblbal
\ No newline at end of file
然后git add和commit:
yjq@ubuntu:~/learn_android$ git add readme.txt
或使用:
yjq@ubuntu:~/learn_android$ git add .
将当前目录所有未加入版本的文件add进来。
git status查看:
yjq@ubuntu:~/learn_android$ git status
# On branch master
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
#
# modified: readme.txt
#
git commit提交:
yjq@ubuntu:~/learn_android$ git commit -m "add some content to readme.txt"
[master 5213fcd] add some content to readme.txt
1 file changed, 1 insertion(+)
mode change 100644 => 100755 readme.txt
2、版本回退
执行git log命令可查看我们从最近到最远的详细提交日志,若是想简略的显示,则执行:
git log –pretty==oneline
在Git中使用HEAD表示当前版本,HEAD^ 表示上一个版本,HEAD^^ 表示上上个版本。
回退到上一个版本:git reset –hard HEAD^
回退到版本100644:git reset –hard 100644
回退到某个版本后,若是又想恢复到新版本,先执行:git reflog找到历史命令中自己想要恢复的版本的commit id,然后执行:git reset –hard commit_id
3、工作区和暂存区
Git和其它版本控制系统如SVN的一个不同是拥有暂存区的概念。
工作区(Working Directory):就是在电脑中能看到的目录,比如前面的learn_android目录。
版本库(Repository):即工作区中的隐藏目录“.git”。
Git的版本库里存了最重要的称为stage(或者叫index)的暂存区,还有Git为我们自动创建的第一个分支master,以及指向master的一个指针HEAD。
暂存区就是存放修改后的待提交文件,git add命令就是将要提交的所有修改放到暂存区(Stage),而git commit命令就是将暂存区的所有修改提交到分支。
4、管理修改
git diff HEAD – readme.txt 可以查看工作区和版本库里面最新版本的修改信息。当我们每次修改文件后,若是不把修改内容add进暂存区,那也就无法加入到commit中。
5、撤销修改
git checkout – file 可以丢弃工作区的修改,有可能回到最近一次的git commit状态或是git add时的状态。
note:git checkout file表示创建一个file新分支。
用命令 git reset HEAD file 可以把暂存区的修改撤销掉(unstage),重
新放回工作区。
git reset 命令既可以回退版本,也可以把暂存区的修改回退到工作区。当我们用HEAD时,
表示最新的版本。
6、删除文件
本地删除命令 rm test.txt ,然后版本库中删除命令 git rm test.txt ,若是删除后想恢复 git checkout – test.txt
三、远程仓库
Git是分布式版本控制系统,同一个Git仓库,可以分布到不同的机器上。这里需要有一个原始的版本库,就一现成的Github托管为例,注册账号后,由于本地Git仓库和Git远程仓库之间的传输是通过SSH加密的,所以,设置:
第一步,创建SSH Key,Shell下或Git bash下执行:$ ssh-keygen -t rsa -C “邮件地址”,一路设置,最终可在用户主目录里面生成.ssh目录,里面包含有id_rsa和id_rsa.pub两个文件,这两个就是SSH Key的秘钥对,id_rsa是私钥,不能泄露出去,id_rsa.pub是公钥,可
以放心地告诉任何人。
第二步,登陆GitHub,打开“Account settings”,“SSH Keys”页面,然后点击“Add SSH Key”,填上任意Title,在Key文本框里面黏贴id_rsa.pub文件的内容,然后点击“Add Key”,就可以看到添加成功的Key了。
GitHub允许添加多个Key,以便可以在多台电脑上进行提交。
1、添加远程库
在本地已经创建过一个Git仓库后,我们再在GitHub上创建一个Git仓库,以便进行远程同步。
首先,在GitHub上找到“Create a new repo”按钮,然后创建一个新的Git仓库,在Repository name里面填入learn_android,其他保持默认,点击“Create repository”就可成功创建一个新的Git仓库。
由于GitHub上的learn_android仓库是空的,所以我们将本地仓库与之关联,在本地的learn_android仓库下执行:
$ git remote add origin git@github.com:GitHub账号名/learn_android.git
origin就是远程仓库的名字,也可以改成别的名字。下一步,再将内容推送远程库,执行:
$ git push -u origin master
就是将当前分支master推送到远程。第一次推送加了-u参数,不仅是为了将本地的master分支推送到远程新的master分支,还可以将本地的master分支和远程的master分支关联起来,以便在以后的推送和拉取中简化命令。
之后只要做了修改,只需执行:
$ git push origin master
就可把本地master分支的最新修改推送至GitHub服务端。
2、从远程库克隆
用命令git clone克隆一个本地库:
SSH方式:$ git clone git@github.com:GitHub账号名/仓库名.git
Https方式:**https://github.com/
GitHub账号名/仓库名.git**
Git支持多种协议,包括https,但通过ssh支持的原生git协议速度最快
四、分支管理
1、创建分支与合并分支
创建dev分支,然后切换到dev分支:
$ git checkout -b dev
Switched to a new branch 'dev'
相当于一下两步:
$ git branch dev
$ git checkout dev
Switched to branch 'dev'
git branch查看分支:
$ git branch
* dev
master
开发过程,现在dev分支开发,完成后,切回到master分支:
$ git checkout master
Switched to branch 'master'
然后合并dev分支到master分支:
$ git merge dev
Updating d17efd8..fec145a
Fast-forward
readme.txt | 1 +
1 file changed, 1 insertion(+)
Fast-forward表示“快进模式”,所以非常快。合并完成后,删除dev分支:
$ git branch -d dev
Deleted branch dev (was fec145a).
再次查看:
$ git branch
* master
2、解决冲突
当当Git无法自动合并分支时,就必须首先解决冲突。解决冲突后,再提交,合并。用 git log –graph 命令可以看到分支合并图,如:
$ git log --graph --pretty=oneline --abbrev-commit
3、分支管理策略
通常,合并分支时,如果可能,Git会用“Fast forward”模式,但这种模式下,删除分支
后,会丢掉分支信息,所以若是想要保留合并的历史,在merge时加上–no-ff参数就会使用普通模式进行合并,而且合并后在版本库中会有记录。如:
git merge --no-ff -m "merge with no-ff" dev
4、Bug分支
若是在某个开发分支工作进行到一半,需要修复一个已有版本的bug,那么先将工作现场储藏起来,执行:
$ git stash
Saved working directory and index state WIP on dev: 6224937 add
merge
HEAD is now at 6224937 add merge
假设需要在master分支进行修改,则创建临时分支,执行:
$ git checkout master
Switched to branch 'master'
Your branch is ahead of 'origin/master' by 6 commits.
$ git checkout -b issue-101
Switched to a new branch 'issue-101'
修改完成后再合并,然后删除临时分支,最后再切回之前的开发分支。
$ git checkout master
Switched to branch 'master'
Your branch is ahead of 'origin/master' by 2 commits.
$ git merge --no-ff -m "merged bug fix 101" issue-101
Merge made by the 'recursive' strategy.
readme.txt | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
$ git branch -d issue-101
Deleted branch issue-101 (was cc17032).
$ git checkout dev
Switched to branch 'dev'
$ git status
# On branch dev
nothing to commit (working directory clean)
回到dev分支后,执行git stash list命令,查看stash的内容:
$ git stash list
stash@{0}: WIP on dev: 6224937 add merge
然后,恢复之前保存的内容,并将stash的内容删除,执行:
$ git stash pop
# On branch dev
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
#
# new file: hello.py
#
# 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
#
Dropped refs/stash@{0} (f624f8e5f082f2df2bed8a4e09c12fd2943bdd40)
或者分别执行:git stash apply恢复和git stash drop来删除。
5、Feature分支
开发一个新feature时,最好新建一个分支,若是要丢弃一个没有被合并过的分支,执行强制删除命令:* git branch -D 分支名称*
6、多人协作
查看远程库的信息命令:git remote:
$ git remote
或者用git remote -v显示更详细的信息:
$ git remote -v
推送本地master分支到远程仓库:
$ git push origin master
推送本地dev分支到远程仓库:
$ git push origin dev
假设要在dev分支上开发,那么创建远程仓库origin的dev分支到本地:
$ git checkout -b dev origin/dev
git push origin dev若是失败,就先用git pull从origin/dev拉取更新,本地合并解决冲突后再推送,若git pull也失败,出现“no tracking information”提示,原因可能是没有指定本地dev分支与远程origin/dev分支的链接,那么,我们设置链接:
$ git branch --set-upstream dev origin/dev
Branch dev set up to track remote branch dev from origin.
然后在git pull。
首先,可以试图用 git push origin branch-name 推送自己的修改;
如果推送失败,则因为远程分支比你的本地更新,需要先用 git pull试图合并;
如果合并有冲突,则解决冲突,并在本地提交;
没有冲突或者解决掉冲突后,再用git push origin branch-name 推送就能成功。
五、标签管理
1、创建标签
首先,切换到打标签的分支:
$ git branch
* dev
master
$ git checkout master
Switched to branch 'master'
然后,用命令 git tag name打标签:
$ git tag v1.0
用命令 git tag 查看所有标签:
$ git tag
v1.0
在commit id是“6224937”的版本上打标签:
$ git tag v0.9 6224937
注:标签不是按时间顺序列出,而是按字母排序的。
用 git show tagname 查看标签信息:
$ git show v0.9
创建带有说明的标签,用-a指定标签名,-m指定说明文字:
$ git tag -a v0.1 -m "version 0.1 released" 3628164
通过-s用私钥签名(签名采用PGP签名的):
$ git tag -s v0.2 -m "signed version 0.2 released" fec145a
一个标签:
2、操作标签
标签打错了,进行删除:
$ git tag -d v0.1
Deleted tag 'v0.1' (was e078af9)
如果要推送某个标签到远程,使用命令 git push origin tagname :
$ git push origin v1.0
或者,一次性推送全部尚未推送到远程的本地标签:
$ git push origin --tags
如果标签已经推送到远程,先从本地删除:
$ git tag -d v0.9
然后,从远程删除。删除命令也是push,但是格式如下:
$ git push origin :refs/tags/v0.9
六、自定义Git
让Git显⽰示颜色
$ git config --global color.ui true
忽略特殊文件,GitHub已经帮忙配置好了https://github.com/github/gitignore
配置别名,如配置git status的别名为st:
$ git config --global alias.st status
配置reset HEAD的别名为unstage:
$ git config --global alias.unstage 'reset HEAD'
配置一个 git last ,让其显示最后一次提交信息:
$ git config --global alias.last 'log -1'
配置有颜色格式等信息的log:
$ 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"