Git使用教程
基本背景
Git 是 Linus Torvalds 为了帮助管理 Linux 内核开发而开发的一个开放源码的分布式版本控制系统。
它采用了分布式版本库的方式,不必服务器端软件支持(注:这得分是用什么样的服务端,使用http协议或者git协议等不太一样。并且在push和pull的时候和服务器端还是有交互的),使源代码的发布和交流极其方便。
Git与SVN区别
Git 不仅仅是个版本控制系统,它也是个内容管理系统(CMS),工作管理系统等。
如果你是一个具有使用 SVN 背景的人,你需要做一定的思想转换,来适应 Git 提供的一些概念和特征。
Git 与 SVN 区别点,这里借用菜鸟教程的一张图说明:
2、Git 把内容按元数据方式存储,而 SVN 是按文件:所有的资源控制系统都是把文件的元信息隐藏在一个类似 .svn、.cvs 等的文件夹里。
3、Git 分支和 SVN 的分支不同:分支在 SVN 中一点都不特别,其实它就是版本库中的另外一个目录。
4、Git 没有一个全局的版本号,而 SVN 有:目前为止这是跟 SVN 相比 Git 缺少的最大的一个特征。
5、Git 的内容完整性要优于 SVN:Git 的内容存储使用的是 SHA-1 哈希算法。这能确保代码内容的完整性,确保在遇到磁盘故障和网络问题时降低对版本库的破坏。
安装
window下的安装及海龟Git的安装配置
Centos/Redhat系列安装
在终端下执行 yum install git
Ubuntu/Debian系列安装
在终端下执行 apt-get install git
编译安装
在https://github.com/git/git/releases 上选取一个版本下载,解压缩后进入到 Git 的目录然后依次执行以下代码:
make configure
./configure
make all
sudo make install
代码管理
Git 工作区、暂存区和版本库
- 工作区:就是你在电脑里能看到的工作目录,某个项目文件夹。
- 暂存区:英文叫stage, 或index。一般存放在 ".git目录下" 下的index文件(.git/index)中,所以我们把暂存区有时也叫作索引(index)。
- 版本库:工作区有一个隐藏目录.git,这个不算工作区,而是Git的版本库
图中我们可以看出此时 "HEAD" 实际是指向 master 分支的一个"游标"。所以图示的命令中出现 HEAD 的地方可以用 master 来替换。
图中的 objects 标识的区域为 Git 的对象库,实际位于 ".git/objects" 目录下,里面包含了创建的各种对象及内容。
我们把文件往Git版本库里添加的时候,是分两步执行的:
- 第一步是用git add把文件添加进去,实际上就是把文件修改添加到暂存区;
- 第二步是用git commit提交更改,实际上就是把暂存区的所有内容提交到当前分支,暂存区的目录树写到版本库(对象库)中,master 分支会做相应的更新。即 master 指向的目录树就是提交时暂存区的目录树。
版本控制
git reset --hard 简洁/完整哈希索引值:回到指定哈希值所对应的版本
git reset --hard HEAD:强制工作区、暂存区、本地库为当前HEAD指针所在的版本
git reset --hard HEAD^:后退一个版本
tip:一个^表示回退一个版本
git reset --hard HEAD~1:后退一个版本
tip:波浪线~后面的数字表示后退几个版本
由上我们可以看出 "HEAD" 实际是指向 master 分支的一个"游标"。所以图示的命令中出现 HEAD 的地方可以用 master 来替换。
git reset HEAD 命令用于取消已缓存的内容;
当执行 "git reset HEAD" 命令时,暂存区的目录树会被重写,被 master 分支指向的目录树所替换,但是工作区不受影响。
假设当前工作目录下有两个文件test.txt、test1.txt现在两个文件修改后,都提交到了缓存区,我们现在要取消其中一个的缓存,操作如下:
$ git status -s
?? test.txt
?? test1.txt
$ git add .
$ git reset HEAD test1.txt
$ git status
On branch master
Your branch is up to date with 'origin/master'.
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
new file: test.txt
Untracked files:
(use "git add <file>..." to include in what will be committed)
test1.txt
提交代码
- (从现有仓库克隆)仓库clone到本地,修改后再push到远程仓库
#将远程仓库克隆到本地
git clone https://github.com/用户个性地址/PictureBed.git
git clone git@github.com:TAT123/PictureBed.git
用户也可以通过配置本地的git配置信息,执行git config命令预先配置好相关的用户信息,配置执行如下:
git config --global user.name "你的名字或昵称"
git config --global user.email "你的邮箱"
平台上的提交邮箱与上面配置信息中的邮箱地址保持一致,这样平台就能及时地统计你在平台中提交代码的贡献了。
修改代码后,在仓库目录下执行下面命令:
#将当前目录所有文件添加到git暂存区
git add .
#提交并备注提交信息
git commit -m "my first commit"
#将本地提交推送到远程仓库
git push origin master
- (工作目录中初始化新仓库)本地初始化一个仓库,设置远程仓库地址后再做push
和方法1的差别,在于先创建仓库。
git init
git remote add origin https://gitee.com/用户个性地址/HelloGitee.git
git pull origin master
新建仓库时,如果在平台仓库上已经存在 readme 或其他文件,在提交时可能会存在冲突,这时用户需要选择的是保留线上的文件或者舍弃线上的文件,如果您舍弃线上的文件,则在推送时选择强制推送,强制推送需要执行下面的命令(默认不推荐该行为):
git push origin master -f
如果您选择保留线上的 readme 文件,则需要先执行:
git pull origin master
分支管理
#创建分支
git branch (branchname)
#切换分支
git checkout (branchname)
#创建并切换到该分支
git checkout -b (branchname)
#列出分支
git branch
#删除分支
git branch -d (branchname)
- 分支合并 git merge
我们创建了一个分支dev,在该分支的上移除了一些文件 test1.txt,然后切换回我们的主分支,删除的 test1.txt 文件又回来了。
$ git checkout -b dev
Switched to a new branch 'dev'
$ git rm test1.txt
rm 'test1.txt'
$ ls
img/ README.md test.txt
$ git add .
$ git commit -am 'remove test1.txt'
[dev aeb6d8d] remove test1.txt
1 file changed, 1 deletion(-)
delete mode 100644 test1.txt
$ git checkout master
$ ls
img/ README.md test.txt test1.txt
使用分支将工作切分开来,从而让我们能够在不同开发环境中做事,并来回切换。我们将 dev 分支合并到主分支去,test.txt 文件被删除。
$ git merge dev
Updating 4f9f7b3..aeb6d8d
Fast-forward
test1.txt | 1 -
1 file changed, 1 deletion(-)
delete mode 100644 test1.txt
git branch
dev
* master
ls
img/ README.md test.txt
解决冲突 git merge
# 在本分支合并其他分支
git merge change_site
# 查看冲突
git diff
# 要告诉 Git
git add
我们创建一个叫做 change_site 的分支,切换过去,我们将 test.txt 内容修改并且提交,切换回master分支我们可以看内容恢复到我们修改前的,我们再次修改 test.txt 文件:
$ git checkout -b change
Switched to a new branch 'change'
$ ls
img/ README.md test.txt
$ cat test.txt
hello git
$ echo 'test change merge' >> test.txt
$ git commit -am "test merge"
#切换回master
$ git checkout master
Switched to branch 'master'
$ echo 'test master merge' >> test.txt
$ git diff
diff --git a/test.txt b/test.txt
index 8d0e412..4815a4a 100644
--- a/test.txt
+++ b/test.txt
@@ -1 +1,2 @@
hello git
$ git commit -am '修改代码'
#查看test.txt的内容
$ cat test.txt
hello git
<<<<<<< HEAD
test master merge
=======
test change merge
>>>>>>> change
#手动修改冲突文件后再提交
git add test.txt
git commit -m 'merge change'
$ cat test.txt
hello git
test master merge
test change merge
更详细的可以查看廖雪峰的网站,
仓库管理
本地仓库与远程仓库交互
git clone <远程库地址>:克隆远程库
功能:①完整的克隆远程库为本地库,②为本地库新建origin别名,③初始化本地库
git remote -v:查看远程库地址别名
git remote add <别名> <远程库地址>:新建远程库地址别名
git remote rm <别名>:删除本地中远程库别名
git push <别名> <分支名>:本地库某个分支推送到远程库,分支必须指定
git pull <别名> <分支名>:把远程库的修改拉取到本地
tip:该命令包括git fetch,git merge
git fetch <远程库别名> <远程库分支名>:抓取远程库的指定分支到本地,但没有合并
git merge <远程库别名/远程库分支名>:将抓取下来的远程的分支,跟当前所在分支进行合并
git fork:复制远程库
tip:一般是外面团队的开发人员fork本团队项目,然后进行开发,之后外面团队发起pull request,然后本团队进行审核,如无问题本团队进行merge(合并)到团队自己的远程库,整个流程就是本团队跟外面团队的协同开发流程,Linux的团队开发成员即为这种工作方式。
公钥管理
公钥配置
Git配置多个SSH-Key
参考配置多个ssh密钥配置
我的配置:
# 添加config配置文件
# 文件内容如下:
# gitee
Host gitee.com
HostName gitee.com
PreferredAuthentications publickey
IdentityFile ~/.ssh/id_rsa
User zfl
# gitlab
Host gitlab.com
HostName gitlab.com
PreferredAuthentications publickey
Port 60019
IdentityFile ~/.ssh/id_rsa
User zfl
# github
Host github.com
HostName github.com
PreferredAuthentications publickey
IdentityFile ~/.ssh/github_id_rsa
User zfl
# 配置文件参数
# Host : Host可以看作是一个你要识别的模式,对识别的模式,进行配置对应的的主机名和ssh文件
# HostName : 要登录主机的主机名
# User : 登录名
# IdentityFile : 指明上面User对应的identityFile路径
工作流程
-
首先,可以试图用git push origin
推送自己的修改; -
如果推送失败,则因为远程分支比你的本地更新,需要先用git pull试图合并;
-
如果合并有冲突,则使用git diff查看冲突,git status查看冲突文件,解决冲突,并在本地提交;
没有冲突或者解决掉冲突后,再用git push origin推送就能成功! -
如果git pull提示no tracking information,则说明本地分支和远程分支的链接关系没有创建,用命令git branch --set-upstream-to
origin/ 。
更详细的可以查看廖雪峰的网站,
这篇博客是为了给实验室新生培训用的,一些地方讲的也不是很全,日后有机会会完善一下。