Git

Git 的介绍与安装

Git具有版本控制与合作开发的特点。它是一个分布式的版本控制系统,代码不仅在服务器上保存代码的完整版,还在各个客户端保存完整代码的副本。这个服务器可以是Github,也可以是自己搭建的代码管理系统,如Gitlab,码云等。

点击进入Git下载页面

GIT的基本结构

工作区

工作区就是当前的Git目录。

版本库

版本库就是该目录下的.git目录。

暂存区

暂存区就是用户执行add操作后,临时修改被放置的位置。暂存区的文件经过commit命令可以被提交到分支中(创建一个版本)。

GIT本地仓库的基本操作

本节将介绍:Git仓库的初始化,版本切换,版本日志的查看,工作区修改情况查看,撤销等命令,命令如下:

1
2
3
4
5
6
7
8
9
10
git init resp_name         # 代码仓库初始化
git add . # 添加所有改动到暂存区
git commit -m "..." # 提交暂存区内容,形成版本
git log # 打印当前版本库
git reflog # 打印操作记录
git reset --hard HEAD^ # 切换到上上个版本
git checkout -- file_name # 将暂存区的文件恢复到工作区(丢弃工作区的改动)
git reset HEAD file_name # 将版本库中的文件恢复到暂存区
git diff HEAD -- file_name # 对比工作区文件与版本库文件的区别
git diff HEAD HEAD^ -- file_name # 对比两个版本的某文件的区别

本地仓库的创建与提交

新建一个目录,之后我们要在这里开发一个项目(编写代码)。首先使用Git Bash在该目录下执行,初始化一个Git仓库:

1
git init

1
git init repository_name

完毕后,Git将创建一个版本控制系统在该目录下。之后我们创建一个文件,简单的编写一些内容,用于验证后面的版本控制的功能。例如,我们创建一个code.txt文件。内容如下:

code.txt

1
Hello

保存退出,在Git Bash中执行以下命令,添加修改到工作区,并提交修改:

1
2
git add . 
git commit -m '新增并初始化了code.txt文件'

这里的.表示该目录下的所有文件,也可以写某一个文件,还可以使用*.txt等格式书写;add操作表示将相应文件加入到版本控制系统中;commit命令表示提交修改,-m的参数表示相应的备注。

版本的切换

输入如下命令,可以查看当前所有的代码版本。

1
git log

或使log以简短形式呈现

1
2
git log --pretty=oneline
git log --graph --pretty=oneline # 含有图形展示

下面我们创建第二个版本。修改刚刚的code.txt文件,内容如下

code.txt

1
2
Hello
World

再次执行

1
2
git add . 
git commit -m '修改了code.txt文件内容'

则我们添加了一个新的版本到我们的版本库中。执行git log即可查看到两个版本。

图中的commit 后的 1f96fe… 与 2f88a26… 则是对应的两个版本的版本代号。

那么如何回退到某一个版本?Git的版本是后一个版本依赖于前一个版本的,也就是后面的版本只记录修改的部分。所有的版本组成了一个链表,而HEAD指针永远指向的最新的版本。如果想找到上一个版本,可以使用HEAD^HEAD~1;上两个版本,可以使用HEAD^^HEAD~2

Tips:HEAD实际上会指向master,而master才指向最新的版本。关于分支的部分可以到下一节查看。这里可以暂时理解为HEAD指向最新的版本。

回退到上一个版本,可以使用命令

1
git reset --hard HEAD^

打开文件code.txt可以看到,文件内容已经恢复到最初的版本了。
如果又想切换到最新的版本,则可以使用命令

1
git reset --hard 版本编号

版本编号可以使用git reflog命令,通过查看操作记录寻找版本编号。

恢复工作区的文件

当工作区被编辑后,如果不知道已经做过哪些修改了,可以通过下面的命令查看当前工作区被修改的情况。

1
git status

如果想撤销工作区中某一个文件的修改,可以使用如下命令

1
git checkout -- 文件名

如果想撤销暂存区中某一个文件的修改,可以使用如下命令,使修改回归暂存区。回归暂存区后,再使用checkout命令使其回到工作区。

1
git reset HEAD 文件名

如何对比文件与文件的不同?

  1. 对比工作区与版本库中的文件的不同:
    使用diff命令,需要给出被对比的版本和文件名。

    1
    git diff HEAD -- 文件名

    会输出

    其中的---表示版本库中的文件,+++表示工作区中的文件。下方的红色部分表示工作区中的文件相对于版本库删掉的部分,绿色的是添加的部分。

  2. 对比版本库中两个版本的文件的不同:
    使用diff命令,并给出被对比的两个版本和文件名。

    1
    git diff HEAD HEAD^ -- 文件名

    这里输出的时候,---表示版本库中的HEAD版本,+++表示HEAD^版本。如果命令写成git diff HEAD^ HEAD,则---+++所表示的内容也相反。

其他命令

如果想删除某一个文件,并将这一改动添加到暂存区,可以使用git add命令,表示添加改动到暂存区;也可以使用git rm命令,表示添加删除操作到暂存区。示例如下:

1
git rm 文件名

Git 的分支管理

在Git中,所谓分支就是一个指针。例如master分支,就是一个master指针指向了该版本链表的某一个节点。如果是其他分支,例如dev分支,则是在这个链表上添加一个叫dev的指针,指向某一个版本节点。最终再由HEAD指针指向当前编辑的分支指针,也就是HEAD指向了当前编辑的分支。

分支的合并,就是将master指针指向dev所指节点,即图中第四个节点。这样就将dev分支合并到master分支当中了。

分支的删除,就是直接删除dev指针,这样就删掉了该分支。

分支的基本操作如下:

1
2
3
4
5
6
7
8
9
git branch           # 查看所有分支
git branch dev # 创建dev分支
git branch -d dev # 删除dev分支
git checkout master # 切换到master分支
git checkout -b dev # 创建并切换到dev分支
git merge dev # 合并dev分支到当前分支
git stash # 临时存储工作区
git stash list # 列出所有的工作区
git stash pop # 恢复顶层的工作区

分支的查看,创建与切换

使用下述命令,可以查看当前的所有分支。

1
git branch

如果要创建某一分支,可以使用这个命令(dev为分支名称)。

1
git branch dev

进行分支切换,可以直接使用如下命令。

1
git checkout master

或创建并切换分支,可以一步到位,使用这个命令。

1
git checkout -b dev

切换的过程,就是由HEAD指向master指针变为了HEAD指向dev指针。新建的分支保留了原有分支的所有版本,也就是版本链表前边的部分,dev与master是共同享有的。这时,我们不论是addcommit操作,还是log操作,均是在dev分支上进行的。

分支的合并与分支管理

当要进行分支合并,使用如下命令,但是分支合并,必须要在被合并的分支上进行,例如要将dev分支合并到master上,需要先切换到master分支上再执行合并操作。

1
git merge dev

合并分为三种情况:有冲突的合并;没有冲突的快速合并;没有冲突的普通合并。

  • 快速合并:只修改新的分支,原有分支不动。例如master指针可以直接指向dev指针的位置上,无需产生新的版本,也不会留下分支创建的记录。
  • 没有冲突的普通合并(recursive合并):两个分支上都有新版本产生,但是没有修改同一个文件。这种情况会在合并后产生一个新的版本。在执行合并操作后会提示提交新版本需要填写的信息。
  • 有冲突的合并:两个分支上都有新版本产生,且修改了同一个文件。这会在合并后先产生合并失败,需要待手动修改冲突后再手动提交新的版本。

对于有冲突的合并,合并失败后,有冲突的文件会产生类似于如下内容的部分。通过手动修改这部分的内容,可以解决合并冲突。修改后,再次执行addcommit操作即可完成合并。

1
2
3
4
5
<<<<<< HEAD   # 删除多余部分,保留需要的部分
原分支的更改(被合并的分支)
========
新传入的更改
>>>>>>> dev

有时为了保留分支的创建与合并的记录,我们会在合并时候禁用快速合并模式。执行方式如下:

1
git merge --no-ff -m "提交信息" dev

合并后,就可以删除dev分支了。这里使用如下命令删除dev分支。

1
git branch -d dev

Bug 分支与 stash 功能

当我们遇到紧急Bug需要修复时,但又不能将当前的工作区提交到版本控制系统中,就可以使用stash功能。

1
git stash

stash功能可以将我们的工作区临时存储起来,存储完成后,工作区恢复到最近版本,就可以先去完成修复Bug的工作了。

修复bug时,首先创建bug分支,其次完成bug修复工作,完成后将bug分支合并到master分支即可。

待完成修复Bug的工作后,再去将我们原来的工作区恢复,继续进行工作。使用如下命令可以看到我们保存的所有的工作现场。

1
git stash list

使用如下命令可以恢复工作现场。

1
git stash pop

Github 的使用

之前的操作都是在本地计算机上所做的。但是我们合作开发的时候,往往需要借用Github之类的代码托管系统。Github的使用,与我们在本地使用Git类似,只是多了拉取与推送等操作。

创建代码仓库

首先需要有一个Github账号,登录后点击New repository,输入仓库名称,配置相应设置后,点击Create repository即可。

.gitignore文件:保存了不需要同步的文件列表。

添加SSH

如果是初次使用Github,需要配置SSH。

点击用户头像->settings->ssh and gpg keys->new ssh key,在这里添加SSH标题与电脑的SSH公钥。

电脑的SSH公钥生成方式:

1
2
cd ~/.ssh/  # 如果提示`No such file or directory`,可以手动的创建一个.ssh文件夹
ssh-keygen -t rsa -C "your_email@youremail.com"

之后按提示输入两遍密码,这个密码可以自己设置一个。也可以什么都不写,直接两次回车键。

用记事本打开.ssh目录下的id_rsa.pub文件,复制里面的内容,到github添加即可。这个公钥也可以移动到其他电脑上使用,用于用户在push时登录Github账号使用,这里建议每台计算机一个公钥。

使用这个命令可以测试SSH是否配置正确。

1
ssh -T git@github.com

使用这两个命令填写用户的用户名和用户邮箱,这里主要是为了在commit时显示是谁提交的代码。这个配置会被保存到用户目录/.gitconfig文件中。

1
2
git config --global user.name "account" 
git config --global user.email "your_email@youremail.com"

后面的Push操作中,还会需要输入一次Github账号密码,这个账号密码与上面的邮箱和账号并不冲突,这个信息只会显示在commit记录上,而Push时输入的账号密码则是用来保证用户访问Github使用的。如果要修改本机上用于Push代码的Github账号密码,可到控制面板->用户账户->管理Windows凭据->普通凭据->git:https://user_name@github.com下修改。

Clone 代码

我们先找到放置项目的目录,使用clone命令将项目克隆到本地。

1
git clone git@github.com:user_name/repo_name

1
git clone https://github.com/user_name/repo_name

如果在克隆的过程中出现错误,可以使用如下命令修复。

1
2
eval "$(ssh-agent -s)"
ssh-add

Push 代码

当代码克隆下来后,首先创建一个自己的分支进行开发。开发完成后,再提交到本地代码库。

1
2
git add .
git commit -m "..."

积累到一定的开发量,如果要推送到远程服务器,则使用如下命令进行远程推送。

1
git push origin dev

其中origin是远程分支(这个名字固定),dev为本地的分支(这个名字随便起)。执行完毕后,远程仓库将创建dev分支。

首次Push时,可能会提示填写Github账号与密码。

如果本地仓库和远程仓库都有代码,且不是一套代码,这里可以使用强推操作。这样的强制操作应该尽量慎重使用。

1
git push -f

也可以先将远程仓库代码与本地代码合并再推送。

1
2
git fetch
git merge

跟踪远程分支

将本地分支跟踪服务器分支。跟踪后,Git将智能提示用户当前分支与服务器分支的进度差别。

1
git branch --set-upstream-to=origin/远程分支名称 本地分支名称

跟踪后,可以直接使用如下代码推送代码。

1
git push

拉去远程分支

1
git pull origin 远程分支名

拉去后,分支会默认进行跟踪。

管理远程分支 Remote 命令

查看远程已存在的分支:

1
git remote 

添加远程仓库,将远程仓库绑定到origin上:

1
git remote add origin 远程仓库

查看远程仓库:

1
git remote -v

可以删除远程主机:

1
git remote rm 主机名

可以修改主机名:

1
git remote rename 原主机名 新主机名

工作中使用Git

  1. 项目经理搭建项目框架,并放入代码管理工具。
  2. 普通员工在自己电脑上生成SSH公钥,交给项目经理。项目经理将SSH公钥上传至服务器。
  3. 项目经理给组员分发代码的克隆地址。组员将代码克隆到自己的电脑上。
  4. 普通员工创建自己的分支,在分支中进行每天的开发。
  5. 注意Master分支要保持发布的代码,Dev分支用于保存开发中的代码。
  6. 组员要把自己的Dev分支发布到远程Dev分支当中,但是发布之前需要确认代码可用,需要经过经理确认。

VS Code GIT

在VS Code中可以看到如下图标,这个图标就是VS Code的Git可视化管理工具。

点击该按钮(源代码管理),点击+,选择当前文件夹,初始化Git本地仓库。这时,Git本地仓库就建立好了。

修改文件夹中的文件,再切换到源代码管理中,将鼠标移动到被修改的文件,可以看到右侧出现了+,点击+可以将操作暂存到暂存区。如果想取消暂存,可以再点-即可。如果选中了某个文件,可以在右侧预览该文件与工作区文件的区别。

最上方有一个,这个是提交按钮,点击后即可提交该版本到版本控制中。

如果想回退到某版本,还是需要借助命令行来实现。这里可以使用插件Git History查看某个版本,复制其ID,方便在命令行操作。

如果想添加远程仓库,也需要借助命令行。可以先执行初始化本地仓库操作,在本地版本库还是空的时候去pull远程代码。也可以跳过初始化操作,直接克隆远程代码。如果在本地版本库不是空的时候直接去pull代码,会出现下面的错误。

1
fatal: refusing to merge unrelated histories

这时可以使用下面的命令强行拉取,这样Git就会不论之前的版本库是否一致,都会去拉去远程分支。

1
git pull https://github.com/用户名/仓库名.git master --allow-unrelated-histories

Visual Studio 2017(待更新)

PyCharm GIT(待更新)

创建本地Git仓库。
VCS->VCS Operation Popup->Create Git Repositry

再次点击VCS,会与之前有所区别。左侧的文件菜单,文件名也会有颜色的变换。

右键左侧某文件或文件夹->Git->Add,将选中文件添加到版本控制中;或者在提交的时候,可以在上方的文件管理器中勾选。

查看版本历史
VCS->Browse VCS Repository->Show Git Repository Log

如果想回退到某一个版本,可以右键一个版本,选择Checkout Revision

如果想切换分支VCS->Git->Branches

使用远程仓库

添加远程仓库:
VCS->Checkout from Version Control

填写远程仓库地址与本地目录:
https://github.com/用户名/仓库名.git

会有提示:
Would you like to open ...
这样就可以打开下载的代码了。

右键左侧某文件或文件夹->Git->Repository->Push推送代码到远程仓库。

PyCharm 其他技巧

PyCharm中没有暂存库的概念,因此代码修改编辑后直接提交即可。

VCS->Git->Annotate 可以看到每一行代码的作者和日期。

自带版本控制VCS->Local History,可以查看本地代码版本。在这里可以直接切换代码版本。

使用Github

配置Git:File -> Settings -> Version Control -> Git
配置Github账号:Version Control -> Github

创建仓库:VCS -> Import into Version Control -> Share Project on Github,填写仓库名称和信息,完成后点share。之后选择要提交的文件。

更新仓库:右键项目 -> Git -> Commit Directory -> Commit

代码回滚:在左下角的Version Control中可以看到提交记录。右键项目 -> Local History -> Show History -> 某一版本右键 -> Revert

参考视频

  1. Git 版本管理
    链接:https://pan.baidu.com/s/1ua94DTk1MkUBlILNDN7LHQ
    提取码:m4un
  2. Git 练习网:https://learngitbranching.js.org/
  3. Git 练习网 Github:https://github.com/pcottle/learnGitBranching

Git 使用

1
2
3
4
5
6
7
8
9
10
11
12
13
# 添加到暂存区
git add files
# 提交到工作区
git commit
# 推送到远程
git push

# 从远程拉去
git pull
# 从工作区恢复版本
git reset
# 从缓存区取出
git checkout

暂存区:本质是一个文件,保存即将提交的文件列表信息。

仓库区:HEAD文件,保存当前指向的分支;index实际存储内容。

分支操作

1
2
3
4
5
git branch  # 所有分支
git branch -r # 远程分支
git branch -d # 删除分支
git branch name # 创建分支
git checkout -b name # 创建并切换
1
2
3
4
5
# fetch 会从远程仓库取新的提交,但是不会修改本地的文件。
git fetch
# pull 会从远程仓库取内容,并将当前分支合并到最新的提交上。
# pull = fetch + merge
git pull