Git的学习与总结

524 阅读10分钟

Git的原理

Git是一种分布式版本控制系统

Git工作区域

Untitled Diagram.png

如上图所示:Git有四个区域:

区域解释
本地工作区域(Working Directory)写代码的工作目录
本地暂缓区(Stage)暂缓区仅是一个文件,临时存放代码的改动,保存即将提交到文件列表的信息
本地仓库(History)安全存放数据的位置,该区域有存放到所有版本的数据,HEAD指向最新放入仓库的版本
远端仓库(Remote Directory)远程仓库,托管代码的服务器

Git文件状态

文件状态解释
untracked未跟踪状态---未将文件加入git库
unmodify暂缓区中,文件快照内容与文件夹一致---变动1:移除暂缓区到untracked状态 变动2:改动文件到 modified状态
modified暂缓区中文件被修改---变动1:加入暂缓区到staged状态 变动2:取消修改到 unmodify状态
staged暂缓区状态---变动1:提交到库中到unmodify状态 变动2:取消修改到modified状态

图解文件状态变化

2.png

上图所示的文件状态变化:

  • 在本地工作目录新创建一个文件 test.txt(untracked状态),通过git add添加到暂缓区(staged状态),最后通过git commit添加到本地仓库。
  • 将暂缓区的文件通过 git rm --cached 移除到本地工作目录,文件状态变为(untracked状态)。

1.png 上图所示的文件状态变化:

  • 通过 git clone 从远程仓库克隆文件到本地工作区,这时所有的文件都是跟踪状态,修改文件hello.java,该文件的状态就会从(unmodify状态)到(modified状态),通过git add添加到暂缓区(staged状态),最后通过git commit添加到本地仓库。
  • 如果修改hello.java文件后,想放弃修改的部分,恢复hello.java文件克隆下来的原始状态,可通过*git checkot --*实现,则hello.java文件的状态就从(modified状态)到(unmodify状态

3.png 上图所示的文件状态变化:

  • 假设Hi.txt文件是从远程仓库克隆下的文件中的一个文档,修改该文件(modified状态),通过git add添加到暂缓区(staged状态),最后通过git commit添加到本地仓库。
  • 提交到本地工作组后再次修改Hi.txt文件,文件的状态就会变为modified状态
  • 修改后的Hi.txt文件通过git add添加到暂缓区(staged状态),可通过 git reset HEAD 将文件的staged状态变为modified状态,即撤销了之前的git add操作。

Git分支介绍

前提与场景设置

  • Git有一个默认分支:master分支
  • 假设新创建了两个文件hello.java和word.java

操作

  1. 在hello.java文件和word.java文件添加内容并提交到本地仓库,提交备注为:submit 1
  2. 修改hello.java文件并提交到本地仓库,提交备注为:submit 2
  3. 修改word.java文件并提交到本地仓库,提交备注为: submit 3
  4. 修改hello.java文件并提交到本地仓库,提交备注为:submit 4
  5. 修改word.java文件并提交到本地仓库,提交备注为: submit 5
  6. 修改hello.java文件并提交到本地仓库,提交备注为:submit 6
  7. 修改word.java文件并提交到本地仓库,提交备注为: submit 7

图视化操作

1.png

如上图所示:红色代表hello.java的修改记录;蓝色代表word.java的修改

存在问题

若将word.java文件通过Git恢复到submit 3的状态,则hello.java文件的状态也会丢失submit 4和submit 6的修改,因此为了让两个模块的修改与回退不受影响,则需要创建新的分支。

创建test分支

git branch test #创建分支test
git checkout -b test #创建test分支,并切换到test分支

2.png

如上图所示:现在存在两个分支master和test(蓝色方块),两个分支是完全一样,都有7次提交,因为test分支是建立在master分支的基础上创建的。

在test分支新提交

修改word.java文件并在test分支上提交,备注为submit 8,产生的效果如下图所示:

3.png

如上图所示: test分支有8次提交,master分支有7次提交,如果在test分支上(蓝色方块)仅供word.java文件的相关操作,则不论如何回退都不会影响hello.java文件。 在日常工作中,一个项目是多人合作的,每个人都从主分支拉取一个属于自己的分支开发

HEAD

  • Git通过HEAD知道当前用户处于哪个分支,所以当用户切换分支,每次打开Git工作目录都会处于切换的目录
  • .git/HEAD文件的内容就是HEAD指针所指向的分支
  • HEAD指针 ——–> 分支指针 ——–> 最新提交

HEAD分离头

  • 分离头的状态其实就是HEAD指针没有指向分支指针,而是直接指向了某个提交,即HEAD的头指针和分支指针分开了。
  • 检出到一个提交就变为分离头状态
  • 在分离头状态修改文件,创建提交
  • 如果想丢弃上述的提交,则直接检出到一个已经存在的分支上
  • 如果想保存上述的提交,使用git checkout -b [分支名称] 创建并检出到一个新的分支,分离头状态的修改就会被保留

Git远程仓库与本地仓库

  • 在代码托管平台Bitbucket、GitLab,GitHub、国内比较著名的代码托管平台有码云、coding等的官网上创建一个远程仓库
  • 本地仓库与远程仓库连接的两个必要条件是:
    1. github账号是远程仓库的成员
    2. github账号中配置了ssh的公钥,ssh的私钥在本地电脑
cd ~/.ssh
ssh-keygen -t rsa -C  Git配置的邮箱地址 #生成公钥,遇到提示直接回车,也可设置密码
sudo vi ~/.ssh/id_rsa.pub # 复制ssh的公钥到github账号

Git命令

基本配置

git config --global user.name  xxx # 配置全局用户名
git config --global user.email xxx@qq.com # 配置全局邮箱

基本操作

git init # 初始化一个Git仓库
git status # 查看文件状态
git add [files] # 本地工作区的内容提交到本地暂缓区
git commit -m "提交备注" # 本地暂缓区的内容提交到本地仓库
git log # 查看所有分支的提交记录,不包括删除了的commit记录
git reflog # 查看所有分支的提交记录,包括删除了的commit记录

工作区与暂缓区差异比较

git diff # 工作区与暂缓区之间的差异
git diff --cached [file] # 暂缓区与最新提交之间的差异
git diff --staged [file] # 暂缓区与最新提交之间的差异
git diff HEAD # 工作区与最新提交之间的差异
git diff commit-id-1 commit-id-2 # 查看两次提交的差异
git diff commit-id-1..commit-id-2 # 查看两次提交的差异
git diff commit-id-1 commit-id-2 >> diff.txt # 查看两次提交的差异,并输出到文件diff中

回退与撤销

git checkout -- files # 撤销本地工作区的修改 
git reset # 重置暂缓区与上一次提交保持一致
git reset HEAD # 重置暂缓区与上一次提交保持一致
git reset –mixed HEAD # 重置暂缓区与上一次提交保持一致
git reset HEAD -- file1 file2 # 针对file1和file2撤销暂缓区的修改
git reset --hard HEAD # 将工作区未提交的与暂缓区修改的都重置到与上一次提交保持一致
git reset --hard commitID # 将工作区和暂缓区回退到指定的提交

远程仓库

git remote -v # 查看远程仓库名称
git remote add [远程仓库名,默认是origin] [远程仓库地址] # 本地仓库关联远程仓库
git push # 如果本地分支和上游的远程分支名字相同,则可使用该命令
git push -u [远程仓库名,默认是origin] [远程仓库分支,默认是master] # 第一次推送本地仓库文件到远程仓库,-u参数会把本地的master分支和远程的master分支关联
git push -u origin test # 推送本地的test分支到远程并关联
git push [远程仓库名] [远程分支] # 本地仓库与远程仓库关联之后的提交命令
git fetch # 将真正的远程分支的更新拉取到本地代表分支,不会更新到本地纯分支
git fetch origin dev # 将远程仓库的dev分支的更新,拉回本地
git pull # git fetch + git merge 

分支

git branch [分支名称] # 创建分支
git checkout [分支名称] # 切换到指定的分支
git checkout -b [分支名称] # 创建并切换到指定分支
git branch # 查看当前所在的分支
git merge [分支名称] # 合并指定分支到当前分支
git branch -d [分支名称] # 删除指定分支
git branch -vv # 查看本地仓库与远程仓库的对应关系
git branch -avv # 查看所有的分支

解决冲突

git merge –abort # 遇到冲突后放弃合并

贮藏与更改

git stash # 保存当前分支的更改
git stash pop # 弹出当前的更改

Git实践

Git的安装

Mac上安装Git

  • 在终端输入命令:git,查看系统是否安装
  • 通过homebrew安装Git: 1.首先安装homebrew:
/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"

2.安装Git

brew install git

Windows上安装Git

  • 从官方网站上下载安装包,按照默认配置快速安装(一直下一步)
  • git的官方网址:git-scm.com/downloads
  • 默认安装完成后,有两种客户端:一种是图形化的客户端,一种是命令行的客户端
  • 图形化的客户端被称之为”Git GUI”
  • 命令行的客户端被称之为”Git Bash”
  • 在系统的”开始”菜单中可以找到”Git GUI”和”Git Bash”,
  • 右键菜单中会多出两个选项,”Git GUI Here”和”Git Bash Here”

Git的基本配置

配置用户信息如下:

git config --global user.name "xxx" # 配置用户名
git config --global user.email "xxxxx" # 配置邮箱
git config --list --global # 查看全局配置

config的三个作用域:

git config --local # 缺省是local,使对应配置只针对当前仓库有效
git config --global # 使对应配置针对当前系统用户的所有仓库生效 
git config --system # 使对应配置针对系统内所有的用户有效

Git与IDEA相结合

  • 在IDEA上导入一个Git项目 点击:File -> New -> Project from Version Control image.png

image.png

  • IDEA上Git面板介绍
  1. 拉取远程仓库的代码: image.png

  2. 提交代码 image.png 提交代码分为四个步骤:

  • 第1步:点击左下方的"commit"
  • 第2步:将本地工作区的改动代码添加到暂缓区(Staged)
  • 第3步:在右边填写提交备注
  • 第4步:点击右下方的"Commit and Push"
  1. 查看各个分支的提交记录(具体到文件差异:command + d 查看文章与上一次提交的差异) image.png

4.右键任意一次的提交记录

image.png

Copy Revision Number # 复制commit- ID
Create Patch # 创建一个补丁,该提交影响的所有文件的一个列表
Cherry-Pick # 在当前分支把其他分支的代码合并过来
Checkout Revision 'dcfcd731' # 检出到当前的提交
show Respository at Revision # 当前提交下文件目录的一个形态
Compare with Local # 与本地文件的对比
Reset Current Branch to Here # 回退代码到当前提交
Revert Commit # 回退当前的提交
Edit Commit Message # 改写提交信息
Squash Into # 相同信息的提交合并为一个大的提交
Drop Commit # 删除当前的提交
Interactively Rebase from Here # 基于当前的提交域本地库做一个rebase
New Branch... # 基于当前的提交创建一个分支
New Tag... # 创建一个标签
Go to Child Commit # 去子提交
Go to Parent Commit # 去父提交

参考文章