Git 常用命令记录

181 阅读11分钟

git:

  • 工作区:即自己当前分支所修改的代码,git add XXX之前的!不包括git add XXX和git commit XXX之后的。
  • 暂存区:已经git add XXX进去,且未git commit -mXXX的
  • 本地分支: 已经git commit -m XXX提交到本地分支的;

初始化并查看仓库当前状态

git init: 初始化本地仓库,会在当前目录下创建一个.git的目录

git status: 查看仓库当前状态

git status -uno:查看仓库当前状态,忽略未跟踪的文件

克隆项目并创建新分支

  • 在任何文件夹下,打开git Bash窗口:通过命令git clone 克隆地址
  • 使用命令git checkout 分支名切换分支
  • 基于当前所在分支创建新分支: git checkout -b 分支名
    • 创建分支:git branch name [tagname](tagname: 标识标签名)
    • 切换分支:git checkout name
    • 创建+切换分支:git checkout -b name
  • 将本地分支推到远程分支:git push origin name
  • 查看所有本地分支:git branch
  • 查看所有远程分支:git branch -r
  • 查看所有本地分支和远程分支:git branch -a

添加文件进暂存区

git add .:提交所有修改的和新建的数据到暂存区(等于git add -A或者gir add -all

git add -u(git add -update):提交所有被删除和修改的文件到数据暂存区

git add -A(git add -all):提交所有被删除、被替换、被修改和新增的文件到数据暂存区 git add *.后缀名:提交通配符匹配的对应后缀的文件到暂存区

暂存Stash

git stash/git stash save:将没有提交的内容缓存并移除,而这条缓存名称为最新一次提交的commit -m的内容,如果没有本地提交则是拉远程仓库时的commit内容

git stash save "xxx";暂存文件

git stash list: 查看暂存文件列表

git stash pop:pop出堆栈中最新的内容应用到当前分支上,且会删除堆栈中的记录;如果pop出来的内容有冲突,git会中断此次pop并告知你需要进行冲突解决;

git stash pop stash@{i}指定pop对应的堆栈记录;

git stash show [堆栈记录]:显示与当前分支差异;举例git stash show @{i}加上-p可以看详细差异。

代码回滚

  1. 在工作区的代码
  • git checkout -- a.txt #丢弃某个文件(文件夹);丢弃目标文件所做的修改(删除的文件会恢复回来,修改的文件会回去)
  • git checkout . 放弃对所有文件的修改

注意:git checkout --file命令中,如果没有--,就变成了“切换到另一个分支的命令”

  • 本地新增了一些文件(并没有 git add 到暂存区),想放弃修改:
    • 单个文件/文件夹:rm -rf filename
    • 所有文件:git clean -xdf
  1. 代码git add到暂存区,并未commit提交
  • git reset HEAD
  • git reset HEAD a.txt(此时回退回来仅仅是把添加到暂存区的的内容回退到工作区,即此时相关文件的内容仍然没有修改,若还需要进一步回退内容,则使用git checkout -- 来回退内容)

这个命令仅改变暂存区,并不改变工作区,这意味着在无任何其他操作的情况下,工作区的实际文件同该命令运行之前无任何变化

  1. git commit 到本地分支,但没有git push到远程
  • git log #得到需要回退一次的commit id
  • git reset --hard <commit_id> 回到你想要的某个版本
  • git reset --hard HEAD^ 回到最新的一次提交
  1. git push把修改提交到远程仓库
  • 通过git reset 是直接删除执行的commit
    • git log 得到需要回退的commit id
    • git reset --hard <commit_id>
    • git push origin HEAD --force强制提交一次,之前错误的提交就从远程仓库删除
  • 通过 git revert 是用一次新的commit来回滚之前的commit
    • git log
    • git revert <commit_id>:撤销指定的版本,撤销也会作为一次提交进行保存
  • git revert 和 git reset的区别
    • git revert是用一次新的commit来回滚之前的commit,此次提交之前的commit都会被保留
    • git reset是回到某次提交,提交及之前的commit都会被保留,但是此commit id之后的修改都会被删除

删除文件

git中,删除也是一个修改;

首先新建一个test.txt文件,添加并添加并提交到仓库(即模拟创建仓库中已经存在的一个文件);

  • 当我们使用命令rm test.txt把目录下的文件删除;此时工作区和版本库变得不一致;使用git status查看状态,指出删除了test.txt文件;现在有两种操作:1、确定从版本库中删除文件;2、从暂存区把误删的文件恢复
    • 确定从版本库中删除文件
      • 使用git rm 删除文件并git commit提交
    • 从暂存区把误删的文件恢复
      • 使用git checkout --file从暂存区恢复误删的文件(本质还是丢弃工作区的改动)

拉取远端代码(git pull与git pull --rebase)

git pull·=== git fetch + git merge FETCH_HEAD

git pull --rebase === git fetch + git rebase FETCH_HEAD

两种的区别是在fetch之后的操作,merge与rebase的不同。 假设当前master的提交如下:

如果你或者你的同事在cid2点,开发进度是cid20(或者突然拉出一个分支,假设是tmp分支),此时要把cid20提交到master

在master执行git merge tmp,然后会得到如下结果:

新增了一次提交记录cid6,似乎也没有什么问题,如果装了小乌龟,查看提交日志,可能就是下面的样子:

业务上体现可能是这样:

merge提交的缺陷:

  1. git 提交记录上分不清每种业务的commit。
  2. graph体现的开发提交的业务记录,在master上比较混乱。
  3. 回滚(如果需要)在当前模式下,繁琐且容易出错。

git rebase

在master执行git rebase tmp之后,操作分支如下:

二者对比可知,rebase没有产生新的节点,使用rebase的git演进路线(提交树)是一直向前的,这样在版本回退时也很容易,用merge的git路线是跳跃的,如果版本回退你也找不到自己想要的版本,如果merge时出现了冲突就麻烦了,当前merge就不能继续进行下去,需要手动修改冲突内容后,add,commit,push而rebase操作的话,会中断rebase,同时会提示去解决冲突,解决冲突后,再执行git rebase --continue继续操作,再push; 想要更好的提交树,建议使用rebase操作会更好一点,这样可以线性的看到每一次提交,并且没有增加提交节点;不过有些项目不建议使用rebase,得看公司与项目的规定。

git pull --rebase 之后如果有合并冲突,使用一下三种方式处理这些冲突:

  • git rebase --abort 会放弃合并,回到rebase操作之前的状态,之前的提交不会丢弃;

  • git rebase --skip则会将引起冲突的commits丢弃掉(慎用)

  • git rebase --continue合并冲突,结合“git add 文件”命令一起修复冲突,提示开发者,一步一步地解决冲突

git log

  • git log在不传参数的情况下,默认查看当前分支的提交记录,显示以下4个字段信息:
    • 提交对象(commit)的完整哈希字串
    • 提交这信息(作者的名字和电子邮件地址)
    • 提交时间
    • 提交说明
  • git log后面可以指定查看哪个分支/tag的提交记录
    • git log origin/master
    • git log test
    • git log v1.0.0
  • git log --oneline用法:使用--oneline,git log信息会变得非常简洁,默认只显示简短的commit id 和提交注释
  • git log --format用法
    • 语法:git log --format=“XXX”
    • 使用实例:git log --format=‘commit id: %h,commit annotation:%s'
  • git log --prety用法
    • git log --pretty实际等价于git log --online

远程名称

  • 一个本地仓库可以关联多个远程仓库的;git remote add origin <repo_address>

git remote add内部做了什么默默无闻的工作呢?他其实是往.git/config中写入了一个叫[remote "origin"]配置;

即git remote add命令,添加了一个叫做origin的远程名称:

  • 其中url参数,表示该远程名称对应的远程仓库地址。
  • 其中fetch参数分为两部分,以冒号:进行分割,冒号左边标识本地仓库文件夹,冒号右边表示远程仓库在本地的副本文件夹。里面的加号+表示往里面添加数据的意思。

当使用git fetch origin时,Git将远程仓库下的所有分支拉取到本地的refs/remotes/origin/目录下,然后git merge时,它会把refs/remote/origin/目录下的对应分支合并到refs/heads/目录下对应分支上。

如果本地的仓库时通过git clone下来的,Git 会默认将远程仓库命令为origin,自动帮你关联上远端仓库(可在.git/config文件中看到已有[remote "origin"]配置项了),因此Commit之后就能直接push了。

  • 注意:origin只是一个名称(别名),用于指向远程仓库。这个别名是可以自行修改的,比如命令为foo,bar等。使用别名的好处是【简单,方便、好记(就像网址和IP的关系)】
    • 既然是别名,就是可修改的;
      • 新增远程名称(一个本地仓库,可以关联多个远程仓库):git remote add
      • 删除已存在远程名称: git remote rm
      • 更新远程名称关联的远程仓库:git remote set-url
      • 修改远程名称(也可以先删除再添加):git remote rename
      • git remote -v:查看本地仓库关联的远程仓库信息;也可以在文件.git/config文件查看

远程分支

远程分支是远程仓库对应分支在本地的一个副本。如常见的origin/master、origin/main、origin/develop等都是远程分支,可以在.git/refs/remotes目录下看到。

git branch:查看所有本地分支

git branch -r:查看所有远程分支

git branch -a: 查看所有本地分支和远程分支

HEAD

  • HEAD存放于本地仓库的.git/HEAD文件里面,利用cat命令:cat .git/HEAD可以看到他的内容
  • HEAD是对当前Commit-ID的引用;如果切换分支,HEAD的内容会跟着改变。
  • 除了git commit之外,git checkout,git reset等命令都会影响HEAD的指向。
    • 当使用git commi时,HEAD会跟着移动,并指向最新的Commit-ID。
    • 当使用git checkout时,HEAD会移动并指向对应分支的最新一个Commit-ID。
    • 当使用git reset时,HEAD会移动至对应分支的某个Commit-ID。请注意git reset --hard可以HEAD和Branch移动至任何地方。git reset的本质就是移动HEAD来达到撤销的目的。

origin/HEAD

origin/HEAD也是一个[远程分支],其中origin则对应远程名称。一般情况下,origin/HEAD总是指向仓库的【默认分支】。假设我们的远程默认分支为main。那么远程仓库在本地的副本,origin/HEAD就是相当于origin/main。Git提供了以下命令让我们去修改origin/HEAD的指向(可通过git remote set-head -h 查看):以下中文解释,假定了远程名称为origin。

git remote set-head <remote-name> -a:将origin/HEAD设为远程仓库的默认分支(-a 即--auto)

git remote set-head <remote-name> <branch-name>:将origin/HEAD设为某个远程分支

比如将git remote set-head origin dev,将origin/HEAD指向远程的dev分支,相当于origin/dev

git remote set0head <remote-name> -d:删除origin/HEAD(-d即 --delete)

ORIG_HEAD

在 .git 目录下,有一个ORIG_HEAD的文件,当我们进行了一些【危险操作】时,比如 git reset, git merge, git rebase 等操作时,Git 会将当前的HEAD指向的Commit-ID原值保存至ORIG_HEAD文件内。需要注意的是,类似git commit 等操作并不会更新ORIG_HEAD的内容。

这样的话,假设我们执行了一些【误操作】时,可以利用 git reset --hard ORIG_HEAD回退至上一步。(ORIG_HEAD:记录高危操作前的Commit-ID;可以使用命令:cat .git/ORIG_HEAD)

如果想吃后悔药了,可以通过 git reset --hard ORIG_HEAD进行回退

FETCH_HEAD

其中 FETCH_HEAD 和 git fetch有关,也是关键部分。

  • FETCH_HEAD 指的是某个分支在远程仓库上最新的状态,每一个执行过git fetch操作的本地仓库都会存在一个FETCH_HEAD 列表,这个列表保存在 .git/FETCH_HEAD 文件中。FETCH_HEAD 文件中的每一行对应着远程仓库的一个分支。当前本地分支执行的FETCH_HEAD 就是该文件中的【第一行】对应的分支。

git查看当前仓库地址

`git remote show origin`

文章参考

https://developer.aliyun.com/article/919354
https://blog.csdn.net/the_power/article/details/104651772/