入职前学了一些git的基础,后来在开发过程中遇到了git回退、“后悔”之类的问题,便索性完整的过了一遍。

练习地址

https://learngitbranching.js.org/?locale=zh_CN

Git 分布式版本控制器

相较于cvssvn这类集中式版本控制器,git的优势在于:
本地版本控制、重写提交说明、可以退回“后悔”、分支系统等。

SVN:增量的分支系统
Git:全量的分支系统(每一个版本都包含全部的文件,时刻保持数据的完整性)


git安装

  1. 网址: msysgit.github.io
  2. 安装:Use git from git bash only..,其他默认下一步
  3. 配置path:F\SystemApp\Git\bin
  4. 配置git(用户名+邮箱):右键选中Git Bash Here
    git config --global user.name "CTX"
    git config --global user.email "348958520@qq.com"
    (注:--system为整个计算机、--global为当前用户、--local为当前项目)

建立git连接

  • 建立ssh免秘钥登陆

本地生成:ssh-keygen -t rsa -C 348958520@qq.com + 一直回车
(默认存放地址:C:UsersCTX.ssh)

发往远端:(个人GitHub→Settings→SSH and...→New SSH:title[协作用户名]+Key[C:\Users\CTX\.ssh\id_rsa.pub的内容]

测试连通:ssh -T git@github.com
(若C:\Users\CTX\.ssh 中出现known_hosts文件则表示成功连通)

  • 把本地文件初始化为git项目:

文件夹里右键选中 Git Bash Here + git init

  • 在GitHub上新建一个仓库生成(区分大小写):

git@github.com:TangSong99/Git_Test.git

  • 本地项目和远程仓库关联

git remote add origin git@github.com:TangSong99/Git_Test.git
git remote -v查看是否关联,若本机之前已存在可以先执行git remote rm origin

第一次发布

  1. git add .
    将当前文件写入暂存区
  2. git commit -m "注释内容"(-m "注释内容"可以替换为回车进行多注释声明)
    暂存区提交到本地分支,默认master(重复提交会显示On branch master nothing to commit, working tree clean,因为commit将文件从暂存区提交到对象区了,暂存区没有东西)
  3. git push -u origin master
    作为主分支提交到仓库中,若不是新仓库即使是清空仓库也会失败(因为先前仓库的库版本会有一个commit readme.md而本地没有导致两个版本不一致,可以用pull更新本地再上传或者git push -f origin master强制覆盖。如果为空仓库建议重新建立仓库。)

第一次下载

  1. git clone git@github.com:TangSong99/Git_Test.git
    下载到本地,再次强调仓库地址区分带小写!

提交本地更新(本地→远程)

  1. git add .
  2. git commit -m "提交到分支"
  3. git push origin master

拉取仓库更新(远程→本地)

  1. git pull

团队协作

发起者:
GitHub仓库的Settings→Manage acess→invite a collaborator→合作者GitHub全名/邮箱→发送邀请链接

协作者:
点击链接参与合作:clone、编写、提交更新(add/commit/push)


实际开发中的项目拉取

实际开发中公司一般用的是自己的GitLab,用申请到的帐号进行登陆,进去后先配一下本地的公钥,git中的name和email也要改成要求的格式。然后进去到对应的项目直接拉取master,开发时再在本地切换需要的分支就行了。

//本地git账户改名(修改之前的提交仍然使用的是之前的邮箱和名字),项目提交前也可以再检查一遍
git config --global "caitianxin"
git config --global "caitianxin@taqu.cn"

//下载项目,SSH下载不了就尝试用HTTP,HTTP需要帐号密码验证
git clone [global's SSH/HTTP]

//打开项目切换分支,VSCode左下角直接切换分支进行开发,可以查看当前分支:
git branch

//要提交前一定要记得先拉取项目到最新!
git pull

//(将AppVersion目录下的文件)提交到暂存区
git add src/views/appConfig/appVersion
//多个文件写法(逗号+空格)
git add src/views/a.vue, src/views/b.vue

//中途可以查看一下是否成功
git status

//提交到本地分支
git commit -m "注释尽量要详细、具体"

//提交到远程仓库
git push

Git执行流程

Git 3+1种状态:

(已管理):项目中被git管理的部分才有以下三种状态
已修改(modified):修改后的代码、暂存区回到工作区(git rm --cached
已暂存(staged):执行add后
已提交(commited):执行commit后


(注:新版git用restore替换checkout)

通过git init将目录纳入git管理,默认为master分支。执行后会生成.git文件,它是git版本控制的目录。


Git回退、删除、后悔、忽略、版本穿梭

  • 从暂存区回到工作区:
    git reset head [filename]
  • 删除已提交到对象区的文件1
    git rm a.txt//删除本地文件和对象区中的a.txt,再把删除文件的操作指令退回到暂存区
    git commit -m "彻底删除a.txt"//相当于重新提交了上一条语句,将a.txt彻底删除

    • git rm xx后的后悔操作
      git restore --staged a.txt
      git restore a.txt
  • 删除已提交到对象区的文件2
    rm a.txt//删除本地文件和对象区中的a.txt,再把删除文件的操作指令退回到工作区
    git add .//提交删除指令到暂存区
    git commit -m "彻底删除a.txt"
  • 重命名(实质上是拷贝一份新名称文件,再把旧的删除)
    git mv a.txt aa.txt,也可以直接mv a.txt aa.txt
  • 注释重写
    git commit --amend -m '修正'
  • 忽略(配置)文件,空文件夹默认忽略 .gitignore

    *.properties
    !a.properties
    #忽略整个目录底下文件
    dir/
    #忽略任意级目录下的txt
    dir/**/*.txt
  • 回退到上一次版本(多人合作的时候要回退最好用指定sha1值或用revert替代reset
    git reset HEAD^ 回退到上两次用HEAD^^,上n次用HEAD~n
  • 指定sha1回退
    git reflog 查看记录,记录所有操作。可以帮助我们 实现“后悔”操作。需要借助于良好的注释习惯
    git reset --hard [sha1值的前几位] reset是将之前增加到暂存区的内容回退到工作区

【注:git reset三种方式的区分放在下面的踩坑场景中了】


Git 日志

git log / git log -number:查看(最近次数)提交的日志

$ git log
commit d433136c1d275fa26fdbf835cc4b2ecd4aeae4ec (HEAD -> master)
Author: CTX <348958520@qq.com>
Date:   Sun Oct 11 11:00:03 2020 +0800

    更新时间2020年10月11日 11:00:22

commit 8bca948ba633f2d93231560573c97da88df74a5b (origin/master, origin/HEAD)
Author: CTX <348958520@qq.com>
Date:   Sun Oct 11 09:49:54 2020 +0800

    更新git进阶

commit 480e0a9184d0f1691de70afe4bcad5943b41b2b8
Author: 唐宋丶 <52407046+TangSong99@users.noreply.github.com>
Date:   Sun Oct 11 09:08:36 2020 +0800

    Create 仓库说明.txt

git log --pretty=online:单行显示简要信息

$ git log --pretty=oneline
d433136c1d275fa26fdbf835cc4b2ecd4aeae4ec (HEAD -> master) 更新时间2020年10月11日 11:00:22
8bca948ba633f2d93231560573c97da88df74a5b (origin/master, origin/HEAD) 更新git进阶
480e0a9184d0f1691de70afe4bcad5943b41b2b8 Create 仓库说明.txt

git log --pretty=format:"%h - %an ,%ar : %s":自定义格式化输出

$ git log --pretty=format:"%h - %an ,%ar : %s"
d433136 - CTX ,7 minutes ago : 更新时间2020年10月11日 11:00:22
8bca948 - CTX ,77 minutes ago : 更新git进阶
480e0a9 - 唐宋丶 ,2 hours ago : Create 仓库说明.txt

其中commit后面跟着的是用sha1计算出的随机数,用于区分是哪一次提交

git log&relog

  • git log 命令可以显示所有提交过的版本信息
  • git reflog 可以查看所有分支的所有操作记录(包括已经被删除的 commit 记录和 reset 的操作)
    例如:执行git reset --hard HEAD~1,退回到上一个版本,用git log则是看不出来被删除的commitid,用git reflog则可以看到被删除的commitid,我们就可以买后悔药,恢复到被删除的那个版本。

Git分支

分支含义为一个commit链,一条工作记录线

  • git branch 查看分支
  • git branch [branch's name] 创建分支
  • git checkout [branch's name] 切换分支
  • git checkout -b [branch's name]创建并切换分支(存在就直接切换)
  • git branch -d [branch's name] 删除分支(不能删除自身和“未合并”内容,未合并可以-D强行删除)
  • git branch -m [old name] [new name] 分支重命名
  • git branch -f [branch's name] [HashCode]强行将分支指定到指定的HashCode
  • git merge [branch's name](主分支执行的)合并操作(合并增/删操作)
    如果一个分支靠前(dev),另一个落后(master)。如果不冲突的话, master可以通过 merge 直接追赶上dev,称为 fast forward。
  • git rebase [branch's name](子分支执行的)合并操作
  • git rebase [branch1] [branch2]将b2合并到b1
  • git checkout [HashCode]^^/[HashCode]~2移动HEAD指向指定HashCode的父父节点
  • git cherry-pick [HashCode1] [HashCode2] [HashCode3]根据HashCode将指定分支s复制到当前分支下
  • git rebase -i [HashCode1]通过可视化界面对HashCode1以后的分支进行删除或者排序
  • git fetch 跟git pull很类似,但是pull是只拉取当前分支到最新,而fetch是拉取所有分支到最新,并且不会切换当前分支

Git现场

stash为保存现场的意思,在功能未没有开发完毕前,不建议commit,且不能切换分支。若要切换要保存现场。

  • 保存现场
    git stash
  • 还原现场(新的不动,旧的替换)
    git stash pop 还原并删除保存
    git stash apply 还原但不删除保存
  • 查看现场
    git stash list

其他

剩下一些差异性、GitHub上的操作、SubTree、Gretty以及GitLab的配置使用
前面的比较简单,后面的目前还用不到,留个坑后续遇到在学吧
Git进阶


记一次Git旧版本覆盖本地代码后的找回

场景:
修改完代码后忘记先pull拉取到最新版本了,直接commit后无法提交报错

error: Your local changes to the following files would be overwritten by merge:
.env.development
vue.config.js
Please commit your changes or stash them before you merge.

解决方案:
卡在暂存区,这时候应该只需要用下面方法撤销commit即可,

git stash
git pull
git stash pop

但是我看了第一篇公众号的方法直接执行了git rebase -i HEAD^导致本地代码直接被昨天提交的覆盖了,真刺激。VSCode没有自带Local History插件后面用一下方法解决:

 git reflog  //查看最近提交状态及其更新的时间
 24d45df5 HEAD@{6}: commit: Android/IOS版本更新
 
 git reset --hard 24d45df5  //回退版本号

【提交前一定要pull同步更新代码!!!】

我的一个朋友踩的坑

场景1:
-commit完后,打算-push时,发现不小心添加了还不想要提交的文件(没开发完只是-add了)。

解决方案:
要注意的是,我之前是因为本地-commit后一番操作变成前一天的版本覆盖了本地,所以本地也要变成-commit那一次的状态,需要用reset --hard
而这次只是提交了还不想提交的东西,所以用reset --soft回退到暂存区的就够了。

1、git log 查看当前分支的历史记录
2、找到你想恢复到的ID,然后 git reset --soft  ID  
3、这样就恢复到了提交之前的状态。被修改提交的文件会被存放在暂存区中,再次提交只需要-commit

git reset 三种回退方式

git reset --soft HEAD~1  head树回到上个版本
回退一个版本,清空对象区,暂存区、工作区都不变,所以本地代码也不变。再次提交只需要-commit

git reset (--mixed) HEAD~1  head树、index树回到上个版本
回退一个版本,清空对象区和暂存区,工作区不变所以本地代码不变。再次提交需要-add、-commit。

git reset --hard HEAD~1  三棵树都回到上个版本
回退一个版本,清空对象区、暂存区和工作区,所以本地代码会被覆盖。

场景2:
当前分支工作一半(部分已经-add),需要切换的新的分支进行工作

解决方案:

1、git stash 暂存区的文件贮藏起来
2、切换分支
3、处理完新分支后回到之前的分支
4、git stash apply 将贮藏的文件重新应用
5、git stash drop 0 移除刚刚贮藏的文件

git stash 指令

git stash list 显示队列
git stash apply [index] 将指定的贮藏的文件重新应用
git stash drop [index] 移除指定贮藏的文件

场景3:
开发分支上有多个commit,本次迭代只需要上其中的某一个commit,需要将这个commit合并到test分支。

解决方案:

1、dev分支git log找到那个commit的SHA-1 校验和 如(62a521)
2、切换到test分支
3、git cherry-pick  62a521
Last modification:March 2nd, 2021 at 03:24 pm
喵ฅฅ