git,一个分布式的版本管理工具。主要用处:版本管理、协作开发。
常见版本管理工具:
VSS ------ Visual Source Safe
CVS ------ Concurrent Versions System
SVN ------ CollabNet Subversion
GIT
GIT安装:下载安装文件:Git-2.41.0-64-bit.exe

运行:
Git是分布式版本控制系统。(另一种是集中式版本控制系统)
分布式版本控制系统没有"中央服务器",每台电脑上都有一个完整的版本库。
就是说,一开始,每台电脑上都有一个一样的版本库,然后每个人不需要联网,就可以做自己的版本控制,添加、修改、删除文件等操作,操作保存在自己本地的版本库中,经过一段时间后,再指定一个统一的地方,大家都把本地的版本库合并到这个统一的地方,实际上就是集中式版本系统的中央服务器,合并中有可能出现各种问题,如冲突等,解决完这些冲突,就形成一个大家都认可的版本,每个人再将这个版本的库下载到本地,再次基础上再次进行开发,循环往复,做到版本控制。
一、版本库创建
版本库又名仓库(repository),创建版本库,需要在一个合适的地方,创建一个空目录:
md e:\learngit
cd learngit
git init
Windows下:

centos6下:

windows下可以使用git bash,环境就是模拟的linux:

windows下可以使用图形界面:即Git GUI

创建仓库后,会创建.git子目录及相关文件、子目录:

二、使用
1、添加文件到仓库:git add filename
需要在learngit目录下创建文件,这个是工作目录,其他地方git是无法管理的


2、提交文件到仓库:git commit -m "说明信息"


第一次提交,出现提示信息,在linux下,默认使用你的登录名和hostname作为user.name和user.email,可以使用git config --global user.name "USERNAME" 和 git config --global user.email "EMAIL"来设置全局的用户名和邮箱地址,来标识提交文件的主人,不带--global,则只在本仓库有效。Windows中,这两项配置文件为C:\Users\Administrator\.gitconfig :

windows下:

配置信息及其保存位置:
git config -l 是三个信息的汇总,分别是:
1).仓库级别 local。 2).用户级别global。 3).系统级别system。
优先级仓库级别最高,用户级别次之,系统级别最低。
1)、仓库级别:git config --local -l

配置文件在仓库的.git目录下的config文件:

2)、用户级别global、 git config --global -l

配置文件在C:\Users\Administrator\.gitconfig
3)、系统界别system. git config --system -l

配置文件在git安装目录下的etc中的gitconfig文件,如:D:\Program Files\Git\etc\gitconfig

在centos6.7中
1)、仓库级别:git config --local -l 配置文件在仓库目录下:.git/config
2)、用户级别global、 git config --global -l 配置文件在用户家目录下的.gitconfig
3)、系统界别system. git config --system -l 配置文件在/etc/gitconfig
3、git status :掌握仓库的当前状态:
当修改了某个文件,而又没有add,更没有commit时,仓库中的文件就与工作区的文件不同了,此时使用gitstatus查看:

git add后

提交后,再次修改:使用git diff a1.txt查看不同:

4、git log 查看提交日志

黄色的字符串,是commit id,即版本号。简洁版的显示

5、git reset 版本回退(或叫版本回滚),恢复到以前的某个版本
Git必须知道当前版本是哪个版本,Git中,用HEAD表示当前版本,上一个版本使用HEAD^表示,上上一个版本用HEAD^^,版本多了,使用HEAD~#,如HEAD~10,回退到往前第10个版本。


如果要再回到第四次的版本,需要先找到第四次的commitid,方法是使用git reflog
git log无法显示回退前的版本信息。

这里看到readme.txt-4的commitid,使用如下命令:
git reset --hard commitid



6、工作区和暂存区
工作区(working Directory):就是电脑中能看到的目录,比如这里的e:\learngit
版本库(Repository):工作区中有一个隐藏目录".git",这个不算工作区,而是Git版本库。
版本库中存了很多东西,其中最重要的就是称为stage(或叫index)的暂存区,Git自动创建的第一个分支master,以及指向master的一个指针叫做HEAD。


把文件往Git版本库⾥添加的时候,是分两步执行的:
第一步是用"git add"把文件添加进去,实际上就是把文件修改添加到暂存区;
第二步是用"git commit"提交更改,实际上就是把暂存区的所有内容提交到当前分支。
因为我们创建Git版本库时,Git自动为我们创建了唯一一个master分支,所以,现在,
commit就是往master分支上提交更改。
需要提交的文件修改通通放到暂存区,然后,一次性提交暂存区的所有修改。
对于第一次修改后,执行了git add,然后又进行了第二次修改,然后直接进行git commit,则在工作区的第二次修改因为没有放入暂存区,所以,git commit只把暂存区的第一次修改提交了,第二次修改不会被提交。
使用:git diff HEAD -- filename 来比较工作区和版本库里面最新版本的区别:

所以,每次工作区的修改最好都add一下,最后一起commit。
7、撤销修改
对于存在不一致的文件,如下:

git提示,可以使用git restore <file>来丢弃工作区的修改

使用git checkout -- <filename>也可以实现。
git restore --staged <file>丢弃暂存区的修改,即git add的修改丢弃,但只是丢弃暂存区的修改,所以执行后,status会回到Changes not staged for commit状态。

关于git checkout命令:
Git社区发布了Git的新版本2.23。在该版本中,有一个特性非常引人瞩目,就是新版本的Git引入了两个新命令 git switch 和 git restore,用以替代现在的 git checkout。换言之,git checkout 将逐渐退出历史舞台。
Git社区决定这样做,是因为目前 git checkout 命令承载了太多的功能,这让新手们感到困惑。git checkout 的核心功能包括两个方面,一个是分支的管理,一个是文件的恢复。这两个核心功能,未来将由 git switch 和 git restore 分别负责。
相比之下,新命令旨在将职责明确分为两个较窄的类别:更改分支的操作和更改文件的操作
8、删除文件
已经提交的文件,在工作区删除了

需要使用git rm <file>执行删除的添加,或者还是使用git add <file>,将删除的信息添加到暂存区,然后git commit,就将仓库中的文件删除了。

恢复:

9、远程仓库:github
本地Git仓库和GitHub仓库之间的传输是通过SSH加密的,所以,需要一点设置:
第1步:创建SSH Key。在用户主目录下,看看有没有.ssh目录,如果有,再看看这个目录下有没有id_rsa和id_rsa.pub这两个文件,如果已经有了,可直接跳到下一步。如果没有,打开Shell(Windows下打开Git Bash),创建SSH Key:
$ ssh-keygen -t rsa -C "youremail@example.com"
需要把邮件地址换成自己的邮件地址,然后一路回车,使用默认值即可,由于这个Key也不是用于军事目的,所以也不需设置密码。在用户主目录中找到.ssh目录,有id_rsa和id_rsa.pub两个文件,这两个就是SSH Key的秘钥对,id_rsa是私钥,不能泄露出去,id_rsa.pub是公钥,可以放心地告诉任何人。
第2步,设置github上的SSH KEY


这样,就可以在本地连接github了。
先在github上创建一个空仓库,learngit:
然后在本地learngit工作区中执行:
git remote add origin git@github.com:kaoa000/learngit.git
这样,就将本地仓库与github上的learngit仓库进行了关联。添加后,远程库的名字就是origin,这是Git默认的叫法,也可以改成别的。
git push -u origin master 将本地仓库推送到远程仓库。
(github访问确实是慢,而且时断时续)

推送前

推送后:

把本地库的内容推送到远程,用git push命令,实际上是把当前分支master推送到远程。
由于远程库是空的,第一次推送master分支时,加上了-u参数,Git不但会把本地的 master分支内容推送的远程新的master分支,还会把本地的master分支和远程的master 分支关联起来,在以后的推送或者拉取时就可以简化命令。
现在只要本地作了提交,就可以通过命令: $ git push origin master
把本地master分支的最新修改推送至GitHub
从远程库克隆:
git clone git@github.com:kaoa000/learngit.git

gitee的使用与github相似:
git remote add origin https://gitee.com/persistself/giteetest.git
git clone https://gitee.com/persistself/giteetest.git
不同的是,需要输入gitee的账号和密码。
10、分支管理:
创建与合并分支:
每次提交,Git都把它们串成一条时间线,这条时间线就是一个分支。目前为止只有一条时间线,在Git中,这个分支叫主分支,即 master分支。
HEAD严格来说不是指向提交,而是指向master,master才是指向提交的,所以,HEAD指向的就是当前分支。
一开始的时候,master分支是一条线,Git用master指向最新的提交,再用HEAD指向master,就能确定当前分支,以及当前分支的提交点:

创建新的分支,如dev,Git新建了一个指针叫dev,指向master相同的提交,再把HEAD指向dev,就表示当前分支在dev上:

从现在开始,对工作区的修改和提交就是针对dev分支了,如新提交一次后,dev 指针往前移动一步,而master指针不变:

在dev上的工作完成了,就可以把dev合并到master上。就是直接把master指向dev的当前提交,就完成了合并:

可以删除dev分支。删除dev分支就是把dev指针给删掉,删掉后,就剩下了一条master分支:

创建dev分支,然后切换到dev分支:
git checkout -b dev
git checkout命令加上-b参数表示创建并切换,相当于以下两条命令:
git branch dev
git checkout dev
使用git branch查看当前分支:

git branch列出所有分支,当前分支前标有一个星号:*
在dev分支上提交:


切换回master:
git checkout master

可以看到,readme.txt中dev分支上提交的修改没有了。因为那个提交是在dev分支上。

现在,把dev分支的工作成果合并到master分支上:
git merge dev :此命令用于合并指定分支到当前分支。

删除dev分支,合并完成后,就可以删除dev分支:
git branch -d dev

Git鼓励大量使用分支:
查看分支:git branch
创建分支:git branch name
切换分支:git checkout name 或 git switch name
创建+切换分支:git checkout -b name 或 git switch -c name
合并某分支到当前分支:git merge name
删除分支:git branch -d name
新版本增加git switch切换分支。
11、解决冲突
git switch -c feature1
修改readme.txt最后一行,在feature1上提交,切换到master分支:
git switch master ,修改readme.txt,然后提交master分支上

此时:

这种情况下,Git无法执行"快速合并",即Fast-forward,这种合并会有冲突:


Git用<<<<<<<,=======,>>>>>>标记出不同分支的内容
修改readme.txt,保存后再次添加提交:

现在,分支变成如下图:

查看合并情况:git log --graph --pretty=oneline --abbrev-commit

删除feature1分支:git branch -d feature1
强行删除分支:git branch -D feature1 :在feature1分支上已经添加并提交,但是还没有合并,可以使用-D强制删除分支。
12、分支管理策略
合并时,使用Fast forward模式,删除分支后,会丢掉分支信息,可以强制禁用Fast forward模式。Git就会在merge时生成一个新的commit,这样从分支历史上就可以看出分支信息。


13、Bug分支:
git stash
git stash list
git stash apply git stash drop
git stash pop
14、多人协作:
从远程仓库克隆时,实际上Git自动把本地的master分支和远程的master分支对应起来了,并且,远程仓库的默认名称是origin。
查看远程库的信息,用:git remote 或git remote -v

抓取(fetch)和推送(push)的origin的地址。如果没有推送权限,就看不到push的地址。
推送分支,就是把该分支上的所有本地提交推送到远程库。推送时,要指定本地分支,这样Git就会把该分支推送到远程库对应的远程分支上:
git push origin master
推送其他分支:git push origin dev


使用push推送的分支,如果远程库中不存在,会创建
抓取分支:其他人克隆远程库,以进行协作开发时,从远程库clone时,默认情况下,只能看到本地的master分支,可以用git branch查看。
要在mydev分支上开发,就必须创建远程origin的mydev分支到本地,使用如下命令创建本地mydev分支:
git checkout -b mydev origin/mydev

冲突及解决:
如果其他人向origin/mydev分支推送了提交,而碰巧自己也对同样的文件做了修改,并试图推送,就会推送失败。其他人先推送

自己修改后又要推送:

解决办法是按照Git的提示,使用git pull把最新的提交从
origin/mydev抓下来,然后在本地合并,解决冲突在推送:

git pull 一开始也出错了,需要git branch --set-upstream-to=origin/mydev mydev关联上

修改完后需要再次git add 和git commit,然后gitpush
其他人要接着开发时,一般先git pull一下,抓取最新的版本,再继续开发:

因此,多人协作的工作模式通常是这样:
-
首先,可以试图用git push origin branch-name推送自己的修改;
-
如果推送失败,则因为远程分支比你的本地更新,需要先用git pull试图合并;
-
如果合并有冲突,则解决冲突,并在本地提交;
-
没有冲突或者解决掉冲突后,再用git push origin branch-name推送就能成功!
如果git pull提示"no tracking information",则说明本地分支和远程分支的链接关系没有创建,用命令git branch --set-upstream-to branch-name origin/branch-name。
多人协作小结
• 查看远程库信息,使用git remote -v;
• 本地新建的分支如果不推送到远程,对其他人就是不可见的;
• 从本地推送分支,使用git push origin branch-name,如果推送失败,先用git pull抓
取远程的新提交;
• 在本地创建和远程分支对应的分支,使用git checkout -b branch-name origin/branchname,本地和远程分支的名称最好一致;
• 建立本地分支和远程分支的关联,使用git branch --set-upstream branch-name
origin/branch-name;
• 从远程抓取分支,使用git pull,如果有冲突,要先处理冲突。
15、忽略文件
在git的工作区的根目录下创建一个特殊的.gitignore文件,然后把要忽略的文件名填进去,Git就会自动忽略这些文件。