Git版本控制工具详解

116 阅读9分钟

安装

  • Git的官网:git-scm.com/downloads;
  • window操作系统按照默认配置全局安装即可
  • Git 自带一个 git config 的工具来帮助设置控制 Git 外观和行为的配置变量

配置

设置你的用户名和邮件地址 设置后 git config --list 查看

git config --global user.name "coderluo"
git config --global user.email "zebluo@qq.com"

文件添加到暂存区 – git add

  • git add aaa.js
  • 通过git add . 将所有的文件添加到暂存区中

文件更新提交 – git commit

commit 命令后添加 -m 选项,将提交信息与命令放在同一行 git commit –m "提交信息"

如果我们修改文件的add操作,加上commit的操作有点繁琐,那么可以将两个命令结合来使用git commit -a -m "修改了文件"

Git的校验和

Git 中所有的数据在存储前都计算校验和(由SHA-1散列算法生成40位数的字符串),然后以校验和来引用, 通常都存在.git仓库的objects文件夹;

查看提交的历史 – git log

git log 可以查看commit记录 简洁的显示:git log --pretty=oneline --graph
git reflog 可以记住包括回退版本的记录

git别名

image.png

获取Git仓库 – git init/git clone

检测文件的状态 - git status

git status –s 可以查看简洁的状态信息

  • Untracked files:未跟踪的文件
  • staged:暂缓区中的文件状态;
  • Unmodified:commit命令,可以将staged中文件提交到Git仓 库
  • Modified:修改了某个文件后,会处于Modified状态; image.png

image.png

版本回退 – git reset

如果想要进行版本回退,我们需要先知道目前处于哪一个版本:Git通过HEAD指针记录当前版本;HEAD 是当前分支引用的指针,它总是指向该分支上的最后一次提交;

image.png 我们可以通过HEAD来改变Git目前的版本指向
上一个版本就是HEAD^,上上一个版本就是HEAD^^
如果是上1000个版本,我们可以使用HEAD~1000;
我们可以可以指定某一个commit id;

git reset --hard HEAD^
git reset --hard HEAD~1000
GIT reset --hard 42fsa212

远程仓库验证

Git Crediential

git config credential.helper 
// manager-core
  • 如果你使用的是 Mac,Git 还有一种 “osxkeychain” 模式,它会将凭证缓存到你系统用户的钥匙串中(加密的)
  • 如果你使用的是 Windows,你可以安装一个叫做 “Git Credential Manager for Windows” 的辅助工具(安装git时会自动安装);可以在 github.com/Microsoft/G… 下载。

SSH密钥

ssh-keygen -t ed25519 -C “your email"

SSH以非对称加密实现身份验证.

  • 例如其中一种方法是使用自动生成的公钥-私钥对来简单地加密网络连接,随后使用密码认证进行登录;
  • 另一种方法是人工生成一对公钥和私钥,通过生成的密钥进行认证,这样就可以在不输入密码的情况下登录;
  • 公钥需要放在待访问的电脑之中,而对应的私钥需要由用户自行保管;

管理远程服务器

查看远程地址

比如我们之前从GitHub上clone下来的代码,它就是有自己的远程仓库的:

git remote 
git remote –v // -v是—verbose的缩写(冗长的)

添加远程地址

我们也可以继续添加远程服务器(让本地的仓库和远程服务器仓库建立连接)

git remote add <shortname> <url>
git remote add test http://152.136.185.210:7888/coderwhy/gitremotedemo.git

重命名远程地址:

git remote rename test test

移除远程地址

git remote remove test

本地分支的上游分支(跟踪分支)

  • 问题一:在本地创建分支后,当前分支没有track的分支

image.png 原因:当前分支没有和远程的origin/master分支进行跟踪; 在没有跟踪的情况下,我们直接执行pull操作的时候必须指定从哪一个远程仓库中的哪一个分支中获取内容;

直接执行git pull是有一个前提的:必须给当前分支设置一个跟踪分支:

git pull <remote> <branch>
// 修改上游分支   `--set-upstream-to`用于修改现有分支
git branch --set-upstream-to=test/main master
// 之后就可以直接使用git pull  
git pull
  • 问题二:直接合并远程分支时,拒绝合并不相干的历史
git fetch test
git branch -u test/main master
git pull

image.png 原因:我们将俩个不相干的分支进行了合并

image.png 简单来说就是:过去git merge允许将两个没有共同基础的分支进行合并,这导致了一个后果:新创建的项目可能被一个毫无戒心的维护者合并了很多没有必要的历史,到一个已经存在的项目中,目前这个命令已经被纠正,但是我们依然可以通过-- allow-unrelated-histories选项来逃逸这个限制,来合并两个独立的项目;

git merge --allow-unrelated-histories
  • 问题三: git push时报错提示如下 image.png

即使我们设置了上游分支,还出现以上报错原因是, 我们在操作git push时 实际上默认是执行 git push origin master(当前分支):master, 但是我们远程上并没有master分支 所以报错了; 那么就是我们本地分支与远程分支不同导致的;

解决方法1:保持本地分支与远程分支相同

// 切换到本地的main分支 并跟踪远程origin的main分支
git checkout -b main --track origin/main
git checkout --track origin/main
git checkout main // 如果本地没有main分支, 就会监测远程是否有main分支,如果有就会创建本地main分支并跟踪远程分支

解决方法2:

// 不缩写git push,使用完整写法
git push origin master:main

解决方法3: 修改当前仓库(非global)push默认值

// 将当前分支push到上游分支
git config push.default upstream
// 将当前分支push到远程的同名分支(如远程没有,会新建一个)
git config push.default current

远程仓库的交互

将代码push到远程仓库

默认情况下是将当前分支(比如master)push到origin远程仓库的

git push
// 推送到远程分支的master分支
git push origin master

从远程仓库fetch代码

默认情况下是从origin中获取代码

git fetch
git fetch origin master

获取到代码后默认并没有合并到本地仓库中,我们需要通过merge来合并;

get merge
get merge origin/master 

从远程仓库pull代码

git pull // 相等于 git fetch + git merge(rebase)

Git标签(tag) - 创建tag

Git 可以给仓库历史中的某一个提交打上标签

git tag v1.0
git tag -a v1.1 -m "附加信息"

默认情况下, git push 命令并不会传送标签到远程仓库服务器上, 在创建完标签后你必须显式地推送标签到共享服务器上

git push origin v1.0
git push origin --tags

删除和检出tag

删除本地tag

git tag -d v1.1

删除远程tag

// git push <remote> -delete <tagname>
git push origin --delete v1.1

检出tag:如果你想查看某个标签所指向的文件版本,可以使用 git checkout 命令,通常我们在检出tag的时候还会创建一个对应的分支

git checkout v1.0

git 分支

  • Git 的分支,其实本质上仅仅是指向提交对象的可变指针
  • Git 的默认分支名字是 master,在多次提交操作之后,你其实已经有一个指向最后那个提交对象的master分支;分支会在每次提交时自动移动;

git 创建分支

git创建分支,他的本质上只是为你创建了一个可以移动的新指针

// 创建分支
git branch testing
// 切换分支
git checkout <name>
// 创建新分支并切换过去
git checkout -b <name>
// 删除当前分支
git branch -d <name> 
// 强制删除某一个分支
git branch -D <name>

image.png git怎么知道当前在哪一个分支上呢? 也很简单,它也是通过一个名为HEAD的特殊指针

image.png 如果我们指向某一个分支,并且在这个分支上提交

image.png 如果我们又切回master分支并提交

image.png

分支开发与合并

当我们在其他分支开发完毕,切换回master分支, 但这个时候master分支也需要其他分支刚刚开发的代码; 所以我们需要将master分支与test分支合并

// 切换回master分支
git checkout master
// 将当前分支与test分支合并
git merge test

image.png

常见的git flow

image.png

git远程分支

  • 远程分支也是一种分支结构:以/的形式命名; 如果是刚刚clone下来的代码,结构如图

image.png 我们可以继续提交master分支,或者git fetch获取远程分支

image.png 操作一:推送分支到远程

    //当你想要公开分享一个分支时,需要将其推送到有写入权限的远程仓库上
    git push origin

操作二:删除远程分支 如果某一个远程分支不再使用,我们想要删除掉,可以运行带有 --delete 选项的 git push 命令来删除一个远程分支

    git push origin -d <branch>

git rebase用法

在 Git 中整合来自不同分支的修改主要有两种方法:merge 以及 rebase。

image.png rebase这个单词如何理解呢?我们可以将其理解成改变当前分支的base;比如在分支experiment上执行rebase master,那么可以改变experiment的base为master

  • 它的原理是首先找到这两个分支(即当前分支 experiment、变基操作的目标基底分支 master) 的最近共同祖先 C2
  • 然后对比当前分支相对于该祖先的历次提交,提取相应的修改并存为临时文件;
  • 然后将当前分支指向目标基底 C3
  • 最后以此将之前另存为临时文件的修改依序应用;

image.png

    // 将experiment分支的base改为master
    git checkout experiment 
    git rebase master
    // 回到master上开发
    git checkout master
    // 将最新的experiment分支与master分支合并, 此时master分支就跟experiment拥有相同的指向, 就可以获取最新代码
    git merge experiment
    

rebase有一条黄金法则:永远不要在主分支上使用rebase, 因为这样主分支就会造成大量的提交历史在main分支中不同

  • merge用于记录git的所有历史,那么分支的历史错综复杂,也全部记录下来;
  • rebase用于简化历史记录,将两个分支的历史简化,整个历史更加简洁;

Git常见命令速查表

image.png