Git 基本操作(1)--命令,原理 | 青训营

130 阅读8分钟

git file lifecycle

  • Modified (working directory):被修改过的文件
  • Staged (staging directory):暂存区文件
  • Committed (git directory):仓库中的文件

基本操作

基础命令

查看状态 git status 

查看记录git log 

查看每一次操作的版本ID号git reflog

初始化git init 

将文件添加到暂存区

git add README.md 

将暂存区的文件打回到工作去

git restore --staged <filename> 

将文件提交到git仓库

git commit -m "-m表示本次提交说明,最好要写" 

当已提交仓库的文件进行修改

git add <filename> df     新版本覆盖旧版本

git restore <filename>       旧版本覆盖新版本(丢弃修改)

回滚快照

git reset HEAD~ 

git reset HEAD~ 其实影响了两棵树:首先是HEAD的指向,将其指向上一个快照(HEAD~);然后再将该位置的快照回滚到暂存区域

git reset --soft HEAD~ 只移动HEAD的指向,但是并不会将快照回滚到暂存区域。相当于撤销了上一次的提交(commit)当提交错了想撤回时用这个

git reset --hard HEAD~ 不仅移动HEAD的指向,将快照回滚到暂存区域,它还将暂存区与的文件还原到工作目录。

再前进到指定版本(往前前进)

git reset 版本号

版本对比

比较暂存区域与工作目录的文件的内容

git diff 

比较两个历史快照的版本

git diff <版本号> <版本号> 

比较当前工作目录和当前版本的快照的内容

git diff HEAD 

比较当前工作目录和Git仓库中的快照的内容

git diff <快照版本号> 

比较暂存区域与Git仓库

git diff --cached

git diff --cached <快照版本号>  

如图↓:

修改、删除和重命名

修改、补足最后一次提交

Situation One:版本刚一提交(commit)到仓库,突然想起漏掉两个文件还没有添加(add)

Situation Two:版本刚一提交(commit)到仓库,突然想起版本说明写得不够全面,无法彰显你本次修改的重大意义……

由于reset 命令过于繁琐,可以用 `git commit --amend 来更正最近一次提交 

不仅可以修改版本说明,还可以把目前暂存区的文件提交上去,但是工作区域文件就不能add+commit

恢复删除文件

删除之后 git status   ,

使用 git restore <file>来恢复删除的文件  

使用 git checkout -- <file>来将暂存区与的文件恢复到工作目录 

删除已经commit的文件

git rm <file>   (rm命令删除的只是工作目录和暂存区与的文件,即取消跟踪,在下次提交时不纳入版本管理)

但是快照中仍然有,只是在暂存区和当前目录不见了,需要再执行

git reset --soft HEAD~ 

删除工作区域/暂存区域的文件

修改已经在暂存区域的文件,那么暂存区域的文件和工作区域的文件就不同了,此时git rm 会删除哪个?

:会报错

git rm -f <file>    删除两个文件 

git rm --cached <file>    删除暂存区,保留工作目录

改名

git vm <OldFileName> <NewFileName>

不让git追踪某些文件

echo *.temp > .gitignore //不追踪*.temp后缀名的文件 

创建和切换分支

假设你的大项目已经上线了(有上百万人在使用),过了一段时间你突然觉得应该添加一些新的功能,但是为了保险起见,你肯定不能在当前项目上直接进行开发,这时候你就有创建分支的需要了。使用分支其实就相当于在说:"我想基于这个提交以及它所有的父提交进行新的工作"

分支命名

master分支

主分支,用于部署生产环境,master分支一般有develop分支和hotfix分支合并,为确保master分支稳定性,任何时间都不能直接修改代码

develop分支

开发分支,始终保持最新完成以及bug修复后的代码,一般开发的新功能时,feature分支都是基于develop分支下创建的

feature分支

开发新功能时,以develop为基础创建feature分支

命名规则:feature/开头的为特性分支,feature/user_moudle、feature/cart_module

release分支

预上线分支,发布提测(提交测试)阶段,会以release分支代码为基准提测。当有一组feature开发完成,首先会合并到develop分支,进入提测时会创建release分支。

如果测试过程中存在bug需要修复,则直接由开发者在release分支修复并提交。当测试完成之后,合并release分支到master和develop分支,此时master为最新代码,用于上线

hotfix分支

修复分支,以hotfix/开头的为修复分支,线上出现紧急问题时,需要及时修复,以master分支为基线,创建hotfix分支,修复完成后,需要合并到master分支和develop分支

创建分支

git branch <name> 

查看分支

git log --decorate

git log --decorate --oneline  (精简)

切换分支:

git checkout <name> 

创建并切换到该分支上

`git checkout -b <name>(创建分支且切换到他那上) 

绘制分支图

git log --decorate --oneline --graph --all

合并与删除分支 

合并分支

HEAD指向主分支的时候

git merge feature

会报错!

合并READPYED.md文件的时候出现冲突。所以合并失败;请修改冲突内容后重新提交结果

在文件中修改一下 然后

git add <file> 

git commit <file> -m "...."  

精髓就是主分支要合并其他分支的时候HEAD要指在住分支上,然后 git merage <其他分支>****


匿名分支和checkout命令

`git checkout HEAD~

You are in 'detached HEAD' state. You can look around, make experimental

changes and commit them, and you can discard any commits you make in this

state without impacting any branches by switching back to a branch.

If you want to create a new branch to retain commits you create, you may

do so (now or later) by using -c with the switch command. Example:

git switch -c

Or undo this operation with:

git switch -

Turn off this advice by setting config variable advice.detachedHead to false

HEAD is now at a603b1e p2

.

你现在处于HEAD指针分离状态,你可以仔细检查,做一些实验性修改并提交他们,并且你可以在这个状态中丢弃任何你所做的提交,而不影响分支,做法是执行checkout命令切回别的分支

如果希望创建一个新的分支并且保持你所做的提交,你可以(现在或稍后)通过使用带有 -c 的命令实现。例如

git switch -c 或者用

git switch - 来撤销这个操作

你使用了checkout分支但是没有指定分支名,所以Git帮你创建了一个匿名分支,既然是匿名,那么当切换到别的分支时,这个匿名分支中的所有提交都会被丢弃掉。所以匿名分支可以用来肆意操作

【p3文件不见了 是因为checkout将环境切换到上一次提交了】

此时,在这个分支下创建一个p4, commit p4,会出现这种情况 。但是当我们在切回master分支,,匿名分支的p4已经荡然无存。

checkout

checkout命令有两种功能:

  • 从历史快照(或暂存区域)中拷贝文件到工作目录
  • 切换分支

从历史快照(或暂存区域)中拷贝文件到工作目录

当给定某个文件名,Git会从指定的提交中copy文件到暂存区和工作目录。如 `git checkout HEAD~ README.md  会将上一个快照中的README.md文件复制到工作目录和暂存区中

                 

如果命令中没有指定具体的快照ID,如 git checkout README.md,则将从暂存区域恢复指定文件到工作目录(README.md) 

(写成 git checkout README.mdgit checkout -- README.md 都行,不过Git比较推荐后者,后者防止混淆 )

切换分支

切换分支的同时也会切换工作去和暂存区

checkout & reset

恢复文件

都可以用于恢复指定快照的指定文件,并且它们都不会改变HEAD指针的指向。

他们的区别是:rest命令只是将指定文件恢复到暂存区域(--mixed) ,而 checkout命令同时覆盖暂存区域和工作目录

恢复快照

reset命令负责回到过去,由于选项不同,reset 命令将移动 HEAD 指针(--soft) -> 覆盖暂存区域(--mixed,默认)-> 覆盖工作目录(--hard)

checkout命令虽说用于切换分支,但实际上也是通过移动HEAD指针和覆盖暂存区域、工作目录来实现的。

区别:

    1. 对于 rest --hardlaishuo ,checkout更安全。因为checkout命令再切换分之前会先检查一下当前的工作状态,如果不是"clean"的话,Git不允许这样做;而reset --hard命令则是直接覆盖所有数据
    2. 更新HEAD指向。rest命令会移动HEAD所在分支的指向,而checkout命令只会移动HEAD自身来指向另一个分支

   

合并分支

通常情况下,Git 会尽可能尝试用 Fast-forward 方式来合并分支,因为这样效率高,只有在万不得已的时候才使用三方合并(Three-way merge)

但是,有时候 Fast-forward 的方式却很容易让我们忽略了分支的存在!

比如:

直接把"feature"分支删除,就会直接丢掉分支的信息:

根本就不知道有个分支存在过……

可有时候我们确实希望保留分支的信息,应该怎么办呢?

只需要在 merge 的时候使用 --no-ff 选项即可告诉 Git 不要使用 Fast-forward 方式合并分支。

这样 Git 就会乖乖地使用三方合并(Three-way merge):

这样就算删掉了“feature”分支,我们仍然可以很容易看出有个分支曾经存在过: