Git 使用工作总结

2,379 阅读8分钟

前言

Git作为技术学习入门阶段就需要掌握的一个技能,很多人或多或少都了解一些相关知识,但是真正要把Git玩的很溜,也是需要花费一点时间的。工作中可能会遇到的一些情况,该如何使用Git解决问题? 例如:

  • commit的代码弄错了怎么处理?
  • 开发工作正在进行到一半的时候,项目负责人要求现在紧急要修复正式版本的一个bug并上线怎么处理?
  • 如何将已经上线的代码进行快速回滚?
  • 已经merge的分支,如何撤销?
  • 已经push过的代码,如何重新提交? 其实这些都是我们经常遇到的问题场景,本文就是自己对Git基础知识的一些学习巩固和总结,主要整理归纳一些工作中遇到的情况所能使用到的Git相关知识,让我们带着这些问题,一起学习理解进步吧!

基本操作

git clone

git clone <gitAddress>
// 可自定义目录名称
git clone <gitAddress> <porjectName>

总体流程

工作区(Workspace) -> 暂存区(Index) -> 本地仓库(Repository) -> 远程仓库(Remote)

git add

工作区(Workspace) -> 暂存区(Index)

// 添加工作区中某个文件至暂存区
git add <fileName>
git add <fileName1> <fileName2> <fileName3>
// 添加工作区中全部文件至暂存区
git add .

git commit

暂存区(Index) -> 本地仓库(Repository)

// 提交暂存更改,并备注信息
git commit -m 'commit message'
// git add . 与 git commit -m 合并命令
git commit -am 'commit message'

修改最近一次的commit

如果最近一次我们修改的文件有错误,但是又不想再生成一次commit.再或者我们不想每一次开发都提交一次commit,显得commit次数过多,这样我们每次只修改当前的commit

git add .
git commit --amend -m 'commit message'

仅修改commit的备注信息

git commit --amend -m 'new commit message'

git push

本地仓库(Repository) -> 远程仓库(Remote)

// 上传至远程仓库,只能是pull或clone的分支可简写
git push
// 上传本地新建分支不可简写
git push origin <branchName>

推送和拉取简写

如果我本地创建的分支推送到远程仓库,但是我希望以后不再写那么长

dev分支为例

git push origin dev

可以加上参数--set-upstream-u,可以将同名的远程仓库对应起来,后面的推送和拉取就可以简写了

// 第一次推送时进行关联
git push -u origin dev
// 第一次没有关联,设置和远程同名分支关联
git branch --set-upstream-to=origin/dev dev

简写后

git push
git pull

git pull

// 可理解为git fetch origin HEAD,再执行git merge HEAD
git pull
// 拉取制定分支git fetch origin <featureName>, 再执行git merge origin/<featureName>
git pull origin <featureName>

一般来说,我们只拉取当前分支的内容,即feature1分支时,拉取远程仓库feature1的内容,由于pull含有merge操作,如果当前分支与拉取分支不统一会造成拉取分支的内容被merge到当前分支

git fetch

git fetch是真的被忽略的一个很有用的命令,它是git pull的第一步,拉取远程仓库的分支至本地的,但是只是本地存储,并没有和你自己的本地仓库有任何联系

// 拉取远程仓库分支
git fetch origin <featureName>
// 拉取所有远程仓库的分支
git fetch --all

拉取前想查看内容

// 拉取
git fetch origin <featureName>
// 查看日志
git log origin/<featureName>
// 切换分支
git checkout <featureName>
// 合并分支
git merge origin/<featureName>

拉取一个本地没有的分支

方法一

git fetch
git checkout -b <featureName> origin/<featureName>

方法二(推荐)

git fetch
git checkout <featureName>

即当我们checkout分支名后,会自动设置以关联远程分支

image.png

git branch

// 新建分支
git branch <branchName>
// 查看分支
git branch
// 查看远程分支
git branch -r
// 查看本地分支和远程分支
git branch -a
// 删除分支
git branch -d <branchName>
// 重命名分支
git branch -m <oldBranchName> <newBranchName>

git checkout

// 切换分支
git checkout <branchName>
// 新建分支并切换
git checkout -b <branchName>

git log

// 查看历史记录
git log
// 查看详细历史记录 --patch或-p
git log -p
// 查看历史记录简要统计
git log --stat
// 查看当前commit改动

git show

// 查看当前commit具体修改内容
git show
// 查看某个commit具体修改内容(最少写四位)
git show <commit-id>
git show 84b8edd8e

image.png

git merge

// 合并分支
git merge <branchName>

合并出现了冲突

image.png

image.png 此时处于merge冲突待解决的一个状态,git会通过<<<<<>>>>>给你划分当前修改和你要merge的修改,这里由你来决定需要留下哪块的内容,然后修改好后,进行下一步操作

git add .
git commit

如果我们不想解决冲突,回到merge操作前,可以使用

git merge --abort

git rebase

这个命令,其实我认为是我觉得git中稍微有点难理解的命令,因为它有点和merge相似,非常容易混淆 rebase可以理解成将当前分支平移到目标分支的后面

举个🌰

image.png

如果我们想通过rebase进行合并,即将main-2合并到main

git checkout main-2
git rebase main

image.png

可以看到,分支不再分叉

如果出现冲突

// 解决冲突后添加到暂存区
git add .
// 继续变基操作
git rebase --continue
// 取消变基
git rebase --abort

merge和rebase的区别

merge会产生一个merge的提交记录,而且可以通过revert进行撤销 rebase的本质是丢弃现有提交,新建了一模一样内容的提交到目标分支,因此commit-id已经不同了,也不能通过revert撤销.而且不可以对公共分支进行rebase,因为这会破坏公共分支

git cherry-pick

cherry-pick是我认为十分有用的命令,因为在工作中经常遇到一个场景就是我们想要一个分支的功能,但是只是需要这个分支的部分功能,此时cherry-pick就大有作为了.它通过commitcommit-id来进行合并

git cherry-pick <commit-id>

同理,它产生冲突和rebase的解决方式是很相似的

// 解决冲突后添加到暂存区
git add .
// 继续cherry-pick操作
git cherry-pick --continue
// 取消cherry-pick
git cherry-pick --abort

git revert

适合快速回滚

撤销某个提交的操作,可以理解成一个提交的"取反",因为revert也会生成一个提交,而这个提交是用来抵消需要撤销的commit

git revert <commit-id>

也可以回滚多次提交,前开后闭区间,不包括,包括

git revert <commit-id1> <commit-id2>

git reset

适合在个人分支做撤回操作

reset也是撤回的一种方式,有三种参数 soft是一种很安全的操作方式,如果你工作区和暂存区都有代码,那么你回退的时候,也不会收到任何影响,而你之前commit的代码则会回到暂存区

git reset HEAD~1 --soft

mixed是默认方式,如果你暂存区有代码,那么它会将暂存区的内容回退到工作区,不影响工作区的内容,并且你的commit代码则会回到工作区

git reset HEAD~1

hard是一个比较危险的参数,因为如果你使用它就意味着,这个命令将会将暂存区,工作区以及你commit的代码全部清空!如果你的代码没有提交,不要使用这个命令

git reset HEAD~1 --hard

撤销上一次push

get reset HEAD~1 --soft
git add .
git commit -m 'some message'
// 如果发生推送不成功的情况,说明远程分支较新,需要强制推送
git push origin <branchName> --force

撤销上一次commit

mixedsoft其实都可以撤销上一次的commit,只是mixed则会回到工作区

git reset HEAD~1

撤销上一次的merge

git reset HEAD~1 --hard

revert vs reset

  1. revert适合我要保留我的commit,但是其中一个时间点的commit我需要去撤回,它不会影响后面的提交
  2. revert会生成一个提交记录,它能够记录你撤销的操作,并体现在commit
  3. reset适合在自己的分支上进行操作,在开发中有些问题需要撤回提交的时候,这个就很好用了,因为它不会留下任何commit记录

git stash

stash是暂存工作区的一种方式

// 暂存工作区内容
git stash 
// 暂存工作区内容并添加备注
git stash save 'msg'
// 应用最近的一次暂存,并删除暂存记录
git stash pop
// 应用暂存, eg: stash@{0}
git stash apply stash@{<num>}
// 获取暂存列表
git stash list
// 清空所有暂存
git stash clear

停下当前做的事,去解决其他问题

如果我们在我们自己的分支做开发feat-1,现在master出现了bug,需要紧急修复,但是我们的代码正在开发,我们来不及草草收尾的时候,就可以用stash

// 暂存现在的工作区代码
git stash
// 切换到master
git checkout master
// 待修改好后切换回自己的分支
git checkout feat-1
// git stash pop

这样,自己开发的内容就回来了~

同步远程分支

如果有的远程分支已经删除了,但是通过git branch -r它仍然存在,可以刷新本地的origin,与远程仓库保持同步

首先,可以先看下有哪些已经不再track(跟踪)的分支

git remote show origin

刷新本地origin分支

git remote prune origin