我常用到的git命令

358 阅读12分钟

掘金小测

juejin.cn/book/684473…
有用的链接 www.cnblogs.com/best/p/7474…
learngitbranching.js.org/
marklodato.github.io/visual-git-…
github.com/geeeeeeeeek…

git文件状态图

git原理图

撤销

从本地的版本回滚并把新建的文件也删除

git clean常和git reset --hard一起结合使用. reset只影响被track过的文件, 所以需要clean删除没有track过的文件. 结合使用这两个命令能让你的工作目录完全回到一个指定的状态

  • git log
  • git reset --hard xxx
  • git clean -df // f:文件 d:文件夹

git remote set-url / add

 git remote add origin git@github.com:ryanchosen/webpack-demo-1.git   // 初次
 git remote set-url origin git@github.com:ryanchosen/webpack-demo-1.git   // 后面想改这个origin的地址

误操作了当前分支的一些东西,想把它恢复成上一次提交的东西

  • git reset --hard HEAD

git checkout不同分支时遇到的情况

  • 当git checkout B 从A 切到B
  • 当版本A中多了一些东西相较于版本B,则这些多的东西也会被显示在版本B的工作区中,注意不是版本B的暂存区
  • 此时如果还想从版本B中切到别的版本比如git checkout - 则没有任何问题,因为git检查的是版本B的暂存区之前之后有无影响,答案是毫无影响
  • 但是分析一种情况,就是你切到版本B之后对版本B暂存区中已经tracked的文件做出任何操作,那git判断之前之后是有影响的,则不会允许你再次git checkout -切到别的版本去,会提示你
  • 此时你可以把变动提交到版本B的暂存区也可以git checkout -f

git merge A

如何理解git merge?

要记住的一点是 git merge 一个commit节点或者一个branch以后 HEAD仍然处于当下的分支上

  • 我们可以注意到*符号没有变过一直在master分支上对吗
  • merge的是当下所在的节点和另外一个分支的某一个节点,不同的分支其实就意味着内容并不相同,举个例子分支1的内容是文件A+文件B,分支2的内容则是文件A+文件C
  • 因此如果是不同的分支之间的合并势必会导致当前分支往前走一步的情况即图2
  • 但是如果图2中,再切到bugFix上,再merge master则发生如下,这也是符合逻辑的,因为master已经包含了所有的bugFix,所以只需要移动bugFix的指向即可

git checkout commitID

进入旧版本代码,切换了一个旧版本代码的临时分支,注意,这是临时分支而不是master分支,因为某某分支是和它当前所占据的那个commit位置绑定在一起的。

如果你git checkout 某个commitID 则head指向该commitID的节点

git checkout HEAD^

git checkout master^

git checkout master~3

git branch master commitID

Git 的提交记录即每次commit节点,会将当前版本与仓库中的上一个版本进行对比,并把所有的差异打包到一起作为一个提交记录

git branch的初衷是让你按逻辑分解工作到不同的分支

git merge VS git rebase 合并VS变基 改变基底

git merge的缺陷是当我们合并两个没有上下游关系的分支时,git会自动替我们生成一个commit,如果我们遇到特殊情况需要反复merge的时候,就会导致commit的提交记录非常混乱,你根本分不清什么是什么。尤其是当你merge了一个巨大改动的分支之后,你的git log基本上就不用看了,肯定全都是其他人的各种乱七八糟你也不清楚的提交记录。

  • git rebase要小心
  • 当我们rebase了之后再提交合并请求我们的合并记录里面会非常干净,没有多余merge的信息。对于多人协同开发的场景非常有帮助

git pull =git fetch +git merge

  • 在 git pull 的「两步走」中的第一步——git fetch 下载远端仓库内容时,这两个镜像引用得到了更新,也就是上面这个动图中的第一步:origin/master 和 origin/HEAD 移动到了最新的 commit。
  • 而 git pull 的第二步操作 merge 的目标 commit ,是远端仓库的 HEAD,也就是 origin/HEAD ,

git branch -d /-D 的区别

如果push一个本地创建的仓库到origin,那么git push的时候请带上origin与branchName

在 Git 中(2.0 及它之后的版本),默认情况下,你用不加参数的 git push 只能上传那些之前从远端 clone 下来或者 pull 下来的分支,而如果需要 push 你本地的自己创建的分支

git checkout feature1
git push origin feature1

远程仓库的 HEAD 是永远指向它的默认分支 master(如果不修改它的名称的话),并会随着默认分支的移动而移动的

合并时的冲突来自于双方同时修改了同一行

git merge --abort // 由于冲突你选择了放弃merge,那么也要手动取消一下的,你的 Git 仓库就会回到 merge 前的状态

合并时的fast-forward快速前进

merge时候的HEAD落后于merge的目标commit,因此就直接移动过去就好啦,所以叫快速前进

git push origin -d branchName # 用 -d 参数把远程仓库的 branch 也删了

刚刚提交的代码,发现写错了怎么办?

  • 你就先把工作区的内容修改正确
  • 然后惯例add一下
  • 然后amend一下commit节点
git add . 
git commit --amend 

Git 会把当前 commit 里的内容和暂存区里的内容合并起来后创建一个新的 commit,用这个新的 commit 把当前 commit 替换掉。所以 commit --amend 做的事就是它的字面意思:对最新一条 commit 进行修正。

而如果你仅仅是commit的message写错了 你就不需要git add .

git commit --amend // 直接amend即可重新填写message,当然你git add .也行哈

git restore 恢复

把stage中的的文件撤回来,后悔放进stage里面了

git restore --staged fileName //作用是将暂存区的文件从暂存区撤出,但不影响正在书写的

git restore fileName

  • 当前这个文件改坏了我想对这个文件重新改
  • 误删了某个文件,我想恢复它

git reset 详解

git reset 不论是 --mixed / soft /hard 都是不会去动untracked文件的

git reset --soft 会把维持你正在修改的内容,并且把与上个版本不同的文件当作new file让你去add

  • 假如commit节点是c1--->c2这个顺序
  • c1的内容是a文件
  • c2的内容是a文件,b文件
  • 并且用户此刻正在修改a的内容以及b的内容
  • 如果此时执行c2 git reset --soft HEAD^
  • b文件丝毫无恙,b文件会被视作new file,并且b正修改的内容也还在,这虽然有些奇怪,但是这是正常的。因为b的绝大多数内容(存在c2版本中的)会被git由已提交状态变成还没有add状态,而正在书写的内容则维持现状
step1:打开文件夹进入项目git test by Ryan/git reset --soft 
step2:git status // 可以发现a和b都改过但是没有add过

step3:
git reset --soft HEAD^ 
git status
// 可以发现文件b由c1中的commited状态变成c2中的还没有add
// 并且文件a和b中正在书写的内容也还存在,提醒你modified

git reset --hard 会抹去现节点相较于之前的节点对已存在的那些文件的影响,但是会把新的文件保留下去

结论1:只要你动过c1节点中已有的文件的内容的,不管你在不在暂存区,内容全部恢复成c1
结论2:存在于c2暂存区中的新文件,也就是说不是c1中的文件,就全部抹除!
结论3:如果你在c2中新建了一个文件正在书写内容,但你没有放进c2暂存区的话,这是安全的!

  • 假如commit节点是c1--->c2这个顺序
  • c1的内容是a文件
  • c2的内容是a文件,b文件
  • 并且用户此刻正在修改a的内容以及b的内容
  • 并且用户还创建了一个文件c但是没有add,只是正在书写一些内容
  • 并且用户还创建了一个文件d并且add进暂存区了
  • 如果此时执行c2 git reset --soft HEAD^
  • 则文件b整个不在了,a文件正在书写的内容被抹去,c不仅保留了,内容也在,而d一整个都不在了
step1:打开文件夹进入项目git test by Ryan/git reset --hard
step2:git status // 可以发现a和b都改过但是没有add过  并且c文件untracked

step3:
touch d
git add d
// 我们创建一个d并且把它放进暂存区
step4:
git reset --hard HEAD^ 
git status
// 发现c文件保留下来了且内容也在,a文件中正在书写的内容一律抹去,b文件都被抹去了更不要说b正在书写的内容了,d因为add进暂存区了所以也抹去了

reset 不加参数:保留工作目录,并清空暂存区 也就是--mixed

git clean 删除untracked的新文件

git 有自带的clean命令 ,就不需要再用bash rm命令了

  • git clean -nfd // 看一下哪些东西会被删掉,包括了文件包括了目录
  • git clean -df // 删除untracked的文件和目录
  • 以上命令随意加 以指定路径

git push -a --prune 让远程的分支长得和本地的一模一样

git fetch --prune 让本地的分支长得和远程的一模一样

git revert VS git reset

  • git revert 如果我们想撤销之前的某一版本,但是又想保留该目标版本后面的版本,记录下这整个版本变动流程,就可以用这种方法.比如,我们commit了三个版本(版本一、版本二、 版本三),突然发现版本二不行(如:有bug),想要撤销版本二,但又不想影响撤销版本三的提交,就可以用 git revert 命令来反做版本二,生成新的版本四,这个版本四里会保留版本三的东西,但撤销了版本二的东西

  • git reset是回到某次提交,提交及之前的commit都会被保留,但是此commit id之后的修改都会被删除

git checkout 用于撤销对文件的修改

还未add到工作树,

  1. 第一步 git checkout 此命令看一下哪些文件修改过了,然后你复制那个文件名
  2. 第二步 git checkout src/views/NotFound.vue 撤销对这个文件的修改,或者 git checkout . 撤销对所有文件的修改

如何把本地master推至远端仓库?

todo:本地master-> 远端仓库 master

  1. 首先,进入一个带有.git的本地仓库

当你github远程仓库新建完成后,你需要在本地敲以下的命令:

  1. git remote add origin git@github.com:ryanchosen/git-demo-1.git 这句话会在本地.git文件夹里创建一个本项目对应的远程仓库名为origin
  2. git push -u origin master 这条命令是一个缩写: git push -u origin master:master 第一个master是本地的branchName,后面的master是远程的branchName
  • origin 是你设置过的远端仓库在本地的代称
  • git remote -v可以查看origin信息
  • -u upstream 把本地仓库的master分支与远程仓库master分支建立默认连接, 之后只需直接git push

题外话,如果不小心错设成https方式该怎么办?

  • 千万记住不要用https方式,但万一你敲成了https方式,你想修改成ssh方式,它会提醒你fatal: remote origin already exists.
  • 此刻,先去查看origin状态: git remote -v
  • 然后git remote rm origin即可重新添加,意思是删除这个叫origin的远程仓库
  • git remote add origin git@github.com:ryanchosen/git-demo-1.gitgit remote add会在.git/config文件中写入配置

如何把本地另外分支推到远端A?

todo: 本地x 分支-> 远端A x分支

  1. git checkout x
  2. git push -u origin x 同样你需要用这条命令对远端仓库建立连接, .git/config中的信息是对所有的分支都共享的

如何为项目设置第二个远端仓库呢?

  1. git remote add origin2 remoteUrl
  2. git push -u origin2 master 这句话相当于告诉整个本地.git仓库,你下一次git push时系统会自动选择名叫origin2的远端的master分支
git branch --set-upstream <remote-branch>
// 设置当前本地分支的默认远程分支

git branch -M main 作用是修改分支名

git clone 是把所有的分支都克隆到本地

先git pull再git push

git help commandName 速查

删完一个东西以后也是要git add . 的

git branch -a 查看所有分支情况

切分支时不会影响当前硬盘上Untracked或者Added状态的新文件的,但reset切版本的时候则会让当前硬盘上U或者A状态的新文件彻底丢失

切分支之前如果有新建的文件呈untracked状态,切换分支后,该U状态文件依旧会存在于硬盘之上。

已修改但未add到工作树的怎么撤回?git checkout 命令

git checkout - 回到上一个分支 ,用于sh脚本中很方便

git checkout -b bugfix // 新建一个bugfix分支并且切到这个分支上去

git push -u origin main 中upstream的含义

  • 将本地的main分支对应到origin这个仓库的main分支上去,那么之后就可以自动git push了