Git使用

一、git与svn区别

svn集中到中央服务器的,你手中只有版本一小部分版本,而git是分布式的,及每个人的都可以是一个版本中心,所以又叫去中心化,当你需要和别人共享版本时,通过push 和 pull 就可以和git服务器同步,这个服务器可以是任意一台包含版本仓库的服务器。可以类比银行和区块链,比特币的区块链设计就类似git,人手一份全账本,只是用p2p全网同步,而git通常搞个中心化服务来同步,svn像银行,完整账本只有银行有,作为终端节点可以向银行查询账本,但如果某一天银行没了,整个完整账本就没了。

二、git安装与配置

  1. 在Windows上使用Git,可以从Git官网直接下载安装程序,然后按默认选项安装即可。

  2. 配置邮箱和用户名

    #初始化git 的用户名和邮箱, 退出配置查看 , 按Q键
    git config --global user.name  MilesWangZhen	#设置用户名
    git config --global user.mail a@miles			#设置默认邮箱
    git config --list   							#查看配置
    

三、创建版本库并提交

  1. 新建一个gittest目录,目录建议避免中文,通过git init命令把这个目录变成Git可管理的仓库

    git init
    Initialized empty Git repository in C:/Users/chenfu/Desktop/test/gittest/.git/
    
  2. 把文件添加到仓库

    # 把未跟踪的代码或文件,加入跟踪列表
    git add xxx
    

    git add 语法:

    • 添加多个文件:git add a.java b.java
    • 添加目录下所有文件:git add java
    • 添加当前目录下的所有文件:git add .
  3. git status查看文件是否添加成功,绿色表示成功

  4. 将文件提交到本地仓库中

    git commit -m "commit the Java folder"
    

四、版本回退

以回退到上一个版本为例,会有三种方式

当我提交了一个空白的readme文件,使用了 git commit -m "commit the readme file"命令,我想回到只有java文件的版本,则可以使用以下三种方式

  1. 回退到上一个版本,版本就回到了 commit the java folder 版本,此时仓库中就没有readme文件

    #回滚到上一个版本
    git reset --hard HEAD^
    HEAD is now at 77c7dcb commit the java folder
    
  2. 或者我通过查看提交日志的方式,直接回滚到制定版本号

    # 查看日志(输入q即可退出)
    git log
    # 回归到指定的版本,版本号最少4位
    git reset --hard 77c7dcb
    

  3. 查看所有操作日志然后可以看到之前版本回退记录

    # 查看操作日志
    git reflog
    # 回归到指定的版本,版本号最少4位
    git reset --hard 77c7dcb
    

    从这可以看到之前的几次版本操作日志以及提交日志,以及当前处于最新的版本。

  4. 总结

    • 如果确定回滚的是上一个版本,可以使用第一种方式

    • 回到指定版本号可以使用第二种方式确认版本号信息,然后回滚

    • 第三种方式适用于要回滚到后一版本的情况,因为git log只能查看当前和之前的版本

五、工作区,缓存区和分支

  1. 工作区有一个隐藏目录.git是Git的版本库。Git的版本库里存了很多东西,其中最重要的就是称为stage(或者叫index)的暂存区,还有Git为我们自动创建的第一个分支master,以及指向master的一个指针叫HEAD

​ git add之后,就从工作区到了暂存区,commit之后就把暂存区的内容提交到了当前分支中,分支的具体作用后面会提到。

  1. 移除add或commit的文件

    # 一般用于移除暂存区中的文件,文件语法和add一致
    git rm -r --cached xxx
    

    这个命令将暂存区的内容全部清楚,即已经add过的文件取消跟踪,包括已经commit过的文件。

    并且再次提交时如果没有将意外取消跟踪的文件重新add,文件将从版本库中移除,所以此命令最好谨慎操作,并且指定需要取消的文件或文件夹。

  2. 撤销修改

    # 通过checkout命令撤销,文件语法和add一致
    git checkout -- xxx
    
    • 当我已经将内容add时,通过checkout命令获取到是暂存区最新的内容
    • 当我已经将内容commit时,通过checkout命令获取到是当前分支中最新的内容
  3. 删除文件

    删除已经commit的文件,再通过commit命令,将版本库中内容同步删除

    #注意前面没有git,文件语法和add一致
    rm xxx
    # 提交删除操作
    commit -m "delete xxx file"
    

六、分支的理解

分支通俗理解

最开始的分支图

  1. 创建并切换分支

    git checkout -b dev
    
    #等价于
    git branch dev
    git checkout dev
    
    #将本地分支push到远程
    git push origin dev
    

    创建完分支之后

  1. 查看所有分支

    # 当前HEAD指向的dev分支
    git branch
    

  2. 删除readme文件

    dev删除readme文件之后的分支结构, 此时的master还没有删除,当前HEAD指向的dev分支

  3. 合并分支

    #切换会master分支
    git checkout master
    #合并分支
    git merge dev
    

    合并之后的分支结构图,当前HEAD指向的master分支

  1. 删除分支

    git branch -d dev
    git branch -D dev #强制删除
    git push origin --delete dev #删除远程分支
    

    当分支合并完成之后可以删除,因为分支创建只是相当于添加了一个指针,所以删除可以比较随意

  2. 查看分支结构图

    git log --graph
    
  3. 创建分支并关联到远程分支

    git checkout -b dev origin/dev
    

七、解决冲突

git中常见冲突会有两种形式

7.1 第一种

本地版本落后于远程版本,然后pull时产生冲突

这种情形一般是你的同事改了a.java文件并提交到远程,然后你也改了a.java文件,然后你想提交时,发现你的本地版本落后于远程版本,系统提示需要pull一下,这时,由于远程a.java和你本地a.java不一致导致冲突,所以只能手动解决问题。

如你同事提交在a.java中提交的内容是

// 在master分支中测试冲突解决

你修改a.java的内容是

// 在master分支中测试冲突解决
// 冲突问题已经解决

当你执行git push时,提示了错误,大致意思是让你pull一下最新版本,然后你执行了git pull命令冲突就产生了

可以通过git status查看冲突的文件

<<<<<<< HEAD
// 冲突问题已经解决
=======
>>>>>>> 28fdb4d275dc4404e4addb78a356f32143195e71
// 在master分支中测试冲突解决

此时,你的文件已经和版本远程版本一致了,所以你可以将代码改成你想要的,比如优化一下

// 在master分支中测试冲突解决
// 冲突问题已经解决

先add,再commit,最后再push就行了

7.2 第二种

一般是自己本地分支之间的冲突

如当你本地feature分支修改了b.java文件,然后切换到master分支,又修改了b.java文件,然后merge分支feature分支时产生冲突

如通过git checkout -b feature创建并切换到feature分支中,b.java提交的内容是

//测试在feature中解决冲突

通过git checkout master切换到master分支,b.java提交的内容是

//测试在master中解决冲突

此时通过git merge feature合并分支时,就产生冲突,git status可以查看到冲突的文件

<<<<<<< HEAD
//测试在master中解决冲突
=======
//测试在feature中解决冲突
>>>>>>> feature

所以可以根据自己的需求修改文件,如改成

//测试在git中解决冲突

先add,再commit,冲突就解决了

八、远程仓库

远程git仓库推荐使用gitee,github速度不是很快,创建一个gittest仓库。

8.1 关联仓库

提供了两种方式关联到仓库,可以设置当前git账户信息

git config --global user.name "Cash_Hunter"
git config --global user.email "214556924@qq.com"
  • 第一种是本地已经有了仓库,如前面执行过git init的文件夹,通过git remote可以关联,关联之后执行push命令
#origin是版本库的名字,可以取任意名字,可以理解成远程仓库的别名
git remote add origin https://gitee.com/mileswangz/gittest.git
#第一次推送需要使用-u,可以将本地的master分支和远程的关联起来
git push -u origin master
  • 另一种是远程仓库中已经有内容了,可以从远程仓库克隆下来,再推送
git clone https://gitee.com/mileswangz/gittest.git
#修改并提交后,执行git push就行
git push

8.2 查看,修改关联仓库

  • 查看远程库信息

    $ git remote -v
    origin  https://gitee.com/mileswangz/gittest.git (fetch)
    origin  https://gitee.com/mileswangz/gittest.git (push)
    
  • 删除关联关系,指定远程仓库名即可,这里只是删除关联关系,并不会删除远程仓库

    git remote rm origin
    

九、常见错误

9.1 Permission denied

  1. 问题描述

    第一次push 时,输入了正确密码,提示 Permission denied (publickey,gssapi-keyex,gssapi-with-mic,password).

    fatal: Could not read from remote repository.

  2. 问题原因

    问题根源是ssh的问题,由于使用SSH连接,第一次需要配置SSH公钥和密钥

  3. 解决办法

    在任意目录下执行 ssh-keygen -t rsa -C"your_email@example.com",git会在windows的本地用户目录下的 ./ssh 目录下

    生成密钥和公钥 id_rsa 或 id_rsa.pub 两个文件,如C:\Users\你的电脑用户名\.ssh,然后使用公钥id_rsa.pub在git远程中生成密钥

  4. 注意事项

    如果公司的ssh端口不是22,还需要额外在.ssh目录下添加config配置文件,配置具体的端口

    # gitee
    Host #git服务ip地址
    Port #对应的端口
    PreferredAuthentications publickey
    IdentityFile ~/.ssh/id_rsa
    User #用户名
    

9.2 文件资源被占用

具体问题已经不好重现了,所以网上找了张图

  1. 问题描述

    Another git process seems to be running in this repository, e.g.
    an editor opened by ‘git commit’. Please make sure all processes

    are terminated then try again.

  2. 问题原因

    Git原则上是支持多进程同步操作资源的,但是如果出现了崩溃,就会出现这样那样的问题,建议同一时间还是只打开一个Git进程进行版本管理比较好。

  3. 解决办法

    很简单,删除index.lock就行

9.3 master分支受保护

  1. 问题描述

    向master推送时,提示这个错

    Gitlab: You are not allowed to push code to protected branches on this project.

  2. 问题原因

    master分支默认受保护的,及不能直接push

  3. 解决办法

    理论上是可以直接将master分支改成unprotected,但是还是建议直接推送到其他分支,然后由项目管理员去merge

十、参考链接

文章部分参考廖雪峰老师的git教程

十一、补充

11.1 stash状态暂存

git stash这个命令可以将当前的工作状态保存到git栈,在需要的时候再恢复。

当在一个分支的开发工作未完成,却又要切换到另外一个分支进行开发的时候,可以先将自己写好的代码,储存到 git 栈,进行另外一个分支的代码开发。这时候 git stash命令就派上用场了!


git stash #可以多次使用,每次使用,都会生成stash@{num},num是编号
git stash save '注释' #可以添加备注,和git stash无差别
git stash pop #默认恢复git栈中最新的一个stash@{num},该命令会将堆栈中最新保存的内容删除
git stash list #查看当前stash的所有内容
git stash apply stash@{num}  #将堆栈中的内容恢复到当前分支下。这个命令不同于 git stash pop。该命令不会将内容从对堆栈中删除
git stash drop stash@{num} #从堆栈中移除指定的stash
git stash clear #移除全部的stash