什么是Git?

概念

Git是版本管理系统,简单的说就是追踪并管理我们文件的变化

Git中的HEAD、head和master

关系图解:https://juejin.im/entry/59a38c5d6fb9a0248e5cc884

HEAD 当前活跃分支的游标(让Git知道你在哪)== current branch

head commit对象的引用,一个repository可以包含任意数量的head。

head被选择成为”current head“,head就成了HEAD

master 分支,会有一个head

 

Git 命令

基础命令

https://www.ruanyifeng.com/blog/2014/06/git_remote.html

Git——常用命令和进阶命令总结

 

git clone

从远程主机克隆一个库,所用命令

$ git clone <库网址>

// 指定不同的目录名
$ git clone <库网址> <本地目录名> 

// 多种协议 HTTP(s)、SSH、Git(最快)等
$ git clone http[s]://example.com/path/to/repo.git/   
$ git clone ssh://example.com/path/to/repo.git/ 

// 克隆库所使用的远程主机自动被命为origin
// 想使用其他的主机名,需用git clone命令的-o指定。
$ git clone -o <主机名> <库网址>

git checkout

//从dev切换回开发分支时,要是dev某个文件跟开发分支冲突时,他就会弹出一个窗,说这部分文件冲突,问你要怎么处理
smart checkout就会把冲突的这部分内容带到开发分支(没有点进窗口的那些文件处理冲突的话)
force checkout就不会把冲突的这部分内容带到开发分支

git remote

管理远程主机,所用命令

// 列出所有远程主机名
$ git remote 
//origin

// 列出所有远程主机和远程主机的网址
$ git remote -v
//origin  [email protected]:jquery/jquery.git (fetch)
//origin  [email protected]:jquery/jquery.git (push)

// 查看主机详细信息
$ git remote show <主机名>

// 添加远程主机
$ git remote add <主机名> <网址>

// 删除远程主机
$ git remote rm <主机名>

// 远程主机的改名
$ git remote rename <原主机名> <新主机名>

 

git fetch

将远程库的更新取回本地

// 远程主机全部更新取回本地
$ git fetch <远程主机名>

// 远程主机特定分支取回本地
$ git fetch <远程主机名> <分支名>

git pull

取回远程主机某个分支的更新,再与本地的指定分支合并

git pull = git fetch + git merge

// 取回远程回到本地分支并合并
$ git pull <远程主机名> <远程分支名>:<本地分支名>
 
// 取回远程回到本地当前分支并合并
$ git pull <远程主机名> <远程分支名>

// Git自动建立追踪关系,默认同名分支建立追踪关系
$ git pull origin
// 如果当前分支只有一个追踪分支
$ git pull

// 手动建立追踪关系
// 指定master分支追踪origin/next分支
git branch --set-upstream master origin/next

// 在本地删除远程已经删除的分支,不加p默认不会删除
$ git pull -p

// 合并如果需要rebase,这么写:
$ git pull --rebase <远程主机名> <远程分支名>:<本地分支名>

git commit

// git commit方法很简单,主要注意配置项
// --amend 可以用来对上次的提交进行修改
$ git commit --amend

// 使用注意事项:
// 如果commit已经push到远程了,此时amend之后,又希望push,需要-f,因为本地commit和远程commit不一样
// 注意同事如果针对旧commit开发了,amend这样的做法可能会产生影响
// 所以没有push过的commit可以随意修改,但是push上去后,就需要斟酌了

git push

将本地分支的更新,推送到远程主机

$ git push <远程主机名> <本地分支名>:<远程分支名>

// 可省略远程分支名,远程分支不存在会重建
$ git push <远程主机名> <本地分支名>

//省略本地分支,则表示删除远程某分支(推空上去)
$ git push <远程主机名> :<远程分支名>

// 远程本地分支间存在追踪关系
$ git push

// 多个远程主机,可指定默认主机
$ git push -u <远程主机名> <本地分支名>

// push的 simple 方式,默认只推送当前分支
$ git push
// push的 matching 方式,默认会推送所有有对应远程的本地分支
// 修改push的方式:
$ git config --global push.default <push类型>
$ git push // 这样push就会变成对应类型的push
// push 本地所有分支到远程
$ git push --all <远程主机名>

// push **注意事项**:
// 远程版本比本地版本新,push会报错,此时:
$ git pull // 合并差异
$ git push
// 如果确定不合并差异要push:
$ git push --force <远程主机名> 

// push推送标签,默认不push标签
$ git push <远程主机名> --tags

 

其他常用命令:

git branch

查看分支

// 查看远程分支
$ git branch -r

// 查看所有分支
$ git branch -a
* master
  remotes/origin/master
// 本地主机的当前分支是master,远程分支是origin/master 

 

git checkout

// 取回远程更新后,可使用git checkout命令创建一个新的分支
$ git checkout -b newBrach <分支名>
origin/master

 

进阶命令

git reset 和 git revert

https://juejin.im/post/5b0e5adc6fb9a009d82e4f20

Git——常用命令和进阶命令总结

都是回退命令,如果想回退commit 2

 

$ git reset --参数
--soft 回退后2修改的代码被保留并标记为add的状态(git status 是绿色的状态)
--mixed 重置索引,但不重置工作树,更改后的文件标记为未提交(add)的状态。默认操作。
--hard 重置索引和工作树,并且2分支修改的没有了。
--merge 和--hard类似,只不过如果在执行reset命令之前你有改动一些文件并且未提交,merge会保留你的这些修改,hard则不会。

简单理解:
// commit2想回退并不需要代码:
git reset commit1_ID --hard
远程有之前代码,强推 git push -f

// commit2想回退但是保留代码
it reset commit1_ID

// 会直接把回退的commit删除掉

 

// commit2想回退掉
$ git revert commit2_ID
//新增一个commit,把之前2的修改都改回去了

区别:

  1. commitID不一样,使用时注意
  2. reset之后没有commit记录,revert因为是新增一个commit,可看到commit记录;所以reset 是把HEAD向后移动,而git revert是HEAD继续前进,只是新的commit的内容和要revert的内容正好相反,能够抵消要被revert的内容
  3. 同事间协作,revert更好,提醒同事这里有回退操作
  4. 如果不希望commit2之后的3、4消失,只能用 git revert commit2_ID

cherry-pick

http://www.ruanyifeng.com/blog/2020/04/git-cherry-pick.html

将指定commit应用于其他分支。

将代码从一个分支转移到另一个分支:

  1. 需要另一个分支的所有代码变动,git merge
  2. 只需要部分代码变动(某几个提交),Cherry pick
// 将指定的提交commitHash,应用于当前分支。这会在当前分支产生一个新的提交,哈希值不一样。
// commitHash不写默认最新一次
$ git cherry-pick <commitHash>

// 转移多个提交,两种
$ git cherry-pick <HashA> <HashB> <HashC> <HashD>
$ git cherry-pick A^..D

// 配置
// 只更新工作区和暂存区,不产生新的提交。
$ git cherry-pick A^..D --no-commit

// 发生代码冲突,cherry pick会停下来
// 如果已处理好冲突
$ git add .
$ git cherry-pick --continue
// 发生代码冲突后,放弃合并,回到操作前的样子。
$ git cherry-pick --abort
// 发生代码冲突后,退出 Cherry pick,但是不回到操作前的样子
$ git cherry-pick --quit

// 不仅同一个代码库不同分支可以,不同代码库也可以
$ git remote add <库名> <地址>  // 添加了一个远程仓库
$ git fetch target            // 将远程代码抓取到本地
$ git fetch target            // 从远程仓库转移的提交,获取它的哈希值
$ git cherry-pick <commitHash>  // 转移提交

 

git rebase

https://www.jianshu.com/p/4a8f4af4e803

主要是对分支做变基操作,主要的用途:

  1. 分支已经过时落后,需要执行rebase来同步分支的变动
// 一同开发出现冲突,一般比如本地master分支落后了
$ git pull 
$ git rebase
$ git push

//上面三个指令可合并为一个
$ git pull --rebase
  1. 分支合并:

从master分支切除新分支用于开发,此时master分支又有了新的commit,这是希望自己开发的分支同步这些新提交,有两种方法,merge和rebase,两者的区别如下图,简单的说就是merge会污染commit记录,rebase的commit很干净。Git——常用命令和进阶命令总结

// 当前分支rebase到master分支上
$ git rebase master
// rebase实际处理
// <1>把 dev 分支里面的每个 commit 取消掉;
// <2>把上面的操作临时保存成 patch 文件,存在 .git/rebase 目录下;
// <3>把 dev 分支更新到最新的 master 分支;
// <4>把上面保存的 patch 文件应用到 dev 分支上;

// rebase时出现冲突,git 会停止rebase去解决冲突。在解决完冲突后,用 
$ git add . // 更新内容
$ git rebase --continue // 继续余下的patch

// 终止rebase,dev回到之前状态
$ git rebase —abort

 

  1. 合并多个commit:

在开发时,经常对于一个功能开发,有多次commite提交,此时需要把多个commit合并再push

// 合并最近的 4 次提交纪录
$ git rebase -i HEAD~4
$ git rebase -i 要合并的版本之前的版本号
// 自动进入 vi 编辑模式,其中有几个命令,可用来自定义各种合并和提交,:wq保存并退出
p, pick = use commit
r, reword = use commit, but edit the commit message
e, edit = use commit, but stop for amending
s, squash = use commit, but meld into previous commit
f, fixup = like “squash”, but discard this commit’s log message
x, exec = run command (the rest of the line) using shell
d, drop = remove commit
// 例子,多个最后合并weiyige
s commitID
s commitID
s commitID
p commitID

// error: cannot 'squash' without a previous commit
// 此错误是因为合并里面,有已经push的commit,不可以哦

// 退出vi,希望重新进入
$ git rebase --edit-todo

//修改完继续
$ git rebase --continue

 

注意:

因为该操作是危险操作,需注意

  • dev分支只有自己使用,可以rebase操作
  • dev分支上需要 rebase 的所有 commit 历史还没有被push过,就可以安全地使用rebase来操作。

Git 实际使用场景总结

  1. 实际使用时,经常会出现一些冲突(比如git stash pop的文件会和改动的代码有冲突),解决完冲突后,均需git add . ,再进行接下来的操作。

相关文章: