Git原理详解与实用指南

随声附和 提交于 2020-01-13 04:37:09

上手 1:新公司用 Git 管理代码,怎么快速上手?

  1. 安装git;
  2. 在github上创建一个仓库,用来练习,创建完成后,复制仓库地址;
  3. 打开git bash,创建一个放本地仓库的目录,如mkdir myGitProjects;
  4. 进入该目录,执行命令:
git clone 仓库地址 
  1. 拉取代码完成之后,在myGitProjects目录下就出现刚创建的项目,进入之后,创建一个shoppingList.txt,在其中写一些内容。
  2. 查看本地仓库的状态,执行命令:
git status

在这里插入图片描述
文字信息:

  • 你当前在master branch;
  • 当前branch没有落后于origin/master;
  • 本地仓库有untracked files(未追踪的文件),文件名是shoppingList.txt;
  • 可以使用git add来开始追踪文件。

7.追踪文件

git add 文件名

这里使用git add shoppingList.txt,追踪,然后再次执行git status命令,可以看到状态变了。

在这里插入图片描述
文字信息:

  • staged表示文件已经进入了暂存区
  1. 文件提交:
git commit -m "备注信息"

这里使用git add -m “Add “shoppingList.txt””,后,再次执行git log可以看到两次提交记录。

说明暂存区里的文件已经提交到本地仓库了。

  1. 注意:每次提交之前,都执行一次git status,看一下文件的状态,这是一个好习惯。

  2. 把本地仓库的修改提交到中央仓库

git push

总结:
git clone 把中央仓库clone到本地
git add 把文件添加到暂存区
git commit -m “message” 把文件从暂存区提交到本地仓库
git push 本地仓库提交到中央仓库
git status 查看文件状态
git log 查看提交历史记录

上手2:团队工作的基本工作模型

拉取其他人的提交

git pull

如果中央仓库的版本领先本地的版本,需要先git pull,保证本地仓库的版本和中央仓库的一致,再提交git push

进阶1:HEAD、master与branch

  1. HEAD 是指向当前 commit 的引用,它具有唯一性,每个仓库中只有一个 HEAD。在每次提交时它都会自动向前移动到最新 的 commit 。

  2. branch 是一类引用。HEAD 除了直接指向 commit,也可以通过指向某个 branch 来间接指向 commit。当 HEAD 指向一个 branch 时,commit 发生时,HEAD 会带着它所指向的 branch 一起移动。

  3. master 是 Git 中的默认 branch,它和其它 branch 的区别在于:

    1. 新建的仓库中的第一个 commit 会被 master 自动指向;
    2. 在 git clone 时,会自动 checkout 出 master。
  4. branch 的创建、切换和删除:

    1. 创建 branch 的方式是 git branch 名称 或 git checkout -b 名称(创建后自动切换);
    2. 切换的方式是 git checkout 名称;
    3. 删除的方式是 git branch -d 名称。

总结:
git branch 分支名 创建分支
git checkout 分支名 切换分支
git branch -d 分支名 删除分支

进阶2:push的本质

  1. push 是把当前的分支上传到远程仓库,并把这个 branch 的路径上的所有 commits 也一并上传。
  2. push 的时候,如果当前分支是一个本地创建的分支,需要指定远程仓库名和分支名,用 git push origin branch_name 的格式,而不能只用 git push;或者可以通过 git config 修改 push.default 来改变 push 时的行为逻辑。
  3. push 的时候之后上传当前分支,并不会上传 HEAD;远程仓库的 HEAD 是永远指向默认分支(即 master)的。

进阶3:merge:合并commits

把目标branch上的所有commit合并到当前branch上:

-----------------(master)
git merge branch1

特殊情况1:冲突

  1. 解决冲突
    找到有冲突的文件,打开,修改,注意删掉提示线和间隔线
    git add .
    git commit -m “message”
    git push
  2. 撤回合并
git merge --abort

特殊情况2:HEAD领先或落后于目标commit

都不会报错,合并为最新版本

进阶4:Feature Branching:最流行的工作流

1.代码分享

新建分支books写一个功能,写完后推到远程仓库

git checkout -b books
git push origin books

其他人要检验代码:

git pull origin books #这种方式只是拉取了books分支的代码,使用git pull会拉取所有代码
git checkout books

检验完之后,没问题,可以合并到master分支:

git checkout master
git pull
git merge books

把结果推到中央仓库,并把books这个分支删除:

git push
git branch -d books
git push origin -d books #删除远程仓库里的books分支
2.Pull Request

这是仓库服务提供方(比如github)提供的一种便捷功能。

1.把branch push到中央仓库;
2.在中央仓库创建一个Pull Request。
在这里插入图片描述
在这里插入图片描述
其他人可以看到我的commit,并评论。

如果确定可以合并,点击Merge pull request就可以合并到master,而且还有delete按钮可以删除该分支。

3.一人多任务

每个功能都新建一个branch,保证不会对master乱修改

进阶5:关于add

git add .

进阶6:看看都改了什么?

  1. 查看历史中的多个 commit:log
    1. 查看详细改动: git log -p
    2. 查看大致改动:git log --stat
  2. 查看具体某个 commit:show
    1. 要看最新 commit ,直接输入 git show ;要看指定 commit ,输入 git show commit的引用或SHA-1
    2. 如果还要指定文件,在 git show 的最后加上文件名
  3. 查看未提交的内容:diff
    1. 查看暂存区和上一条 commit 的区别:git diff --staged(或 --cached)
    2. 查看工作目录和暂存区的区别:git diff 不加选项参数
    3. 查看工作目录和上一条 commit 的区别:git diff HEAD

高级1:rebase替代merge

切换到branch1分支,执行rebase;

git checkout branch1
git rebase master

切换到master分支,执行merge,把head移动到最新的commit上。

git checkout master
git merge branch1

在这里插入图片描述
在这里插入图片描述
master如果不merge,会导致head仍然在之前的commit位置,会丢失合并之后的一些commit。

如果是两个其他的分支,比如branch1和branch2合并,可以直接rebase,不用merge。

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

第一步:提交错误代码

git add laugh.txt
git commit -m "laugh"

第二步:发现有问题,修改文件,再次提交

vi laugh.txt #修改文件
git add laugh.txt
git commit --amend -m "laugh2"

从git log里可以看到之前的laugh的提交已经被laugh2覆盖。

总结:
git commit --amend

高级3:写错的不是最新的提交,而是倒数第二个?

第一步:把当前commit rebase到指定的commit上

git rebase -i HEAD^^
--等同于
git rebase -i HEAD~2

^ 的用法: ^ 表示把commit往回偏移,偏移量就是 ^ 的个数。

~ 的用法: ~ 后面跟一个数,表示往回偏移,偏移量就是 ~ 后面跟着的数。

在这里插入图片描述
第二步:执行完上一步之后,会进入一个编辑页面,点 i 进入编辑状态,修改pick为edit,然后退出
在这里插入图片描述
第三步:修改完要修改的文件之后,提交

git add laugh.txt
git commit --amend
git rebase --continue

高级4:比错还错,想直接丢弃刚写的提交?

git reset --hard HEAD^ #丢弃刚提交的commit

高级5:想丢弃的也不是最新的提交?

用交互式rebase撤销提交

比如撤销倒数第二条提交:

git rebase -i HEAD^^

之前修改的时候是把pick改为edit,删除的时候是直接把那一行删除。

  • 但要注意如果两次提交针对了同一个文件的修改,且有冲突,最新的提交也没了,但文件里会显示冲突。
用rebase --onto撤销提交
git rebase --onto HEAD^^ HEAD^ branch1

高级6:代码已经push上去了才发现写错?

  1. 如果出错内容在私有 branch:在本地把内容修正后,强制 push (push -f)一次就可以解决;
git push origin branch1 -f
  1. 如果出错内容在 master:不要强制 push,而要用 revert 把写错的 commit 撤销。
git revert HEAD^ #反转倒数第二个commit,两个commit互相抵消

高级7:reset的本质–不止可以撤销提交

三种参数:

  1. –hard:重置位置的同时,清空工作目录的所有改动;
  2. –soft:重置位置的同时,保留工作目录和暂存区的内容,并把重置 HEAD 的位置所导致的新的文件差异放进暂存区。
  3. –mixed(默认):重置位置的同时,保留工作目录的内容,并清空暂存区。
git reset --hard HEAD^
git reset --soft HEAD^
git reset HEAD^

高级8:checkout的本质

本质:签出(checkout)指定的commit

checkout的目标也可以不是branch,而是指定某个commit。

git checkout HEAD^^
git checkout master~5
git checkout 78abc
git checkout 78abc^

这些都是可以的。

另外在git status的提示语中也说明可以使用git checkout – <file> 来撤销对指定文件的修改。

checkout和reset的不同

都可以改变HEAD的位置,最大的区别在于:reset在移动时HEAD会带着它的branch一起移动,而checkout不会。当时用checkout指向其他地方的时候,HEAD会和branch分离。

checkout有一个专门分离HEAD和branch而不用移动HEAD的语句:

git checkout --detach

高级9:先扔掉当前工作,立刻打包,然后再取回来

stash:临时存放工作目录的改动

git stash

这样,工作目录就会被清空,所有改动都保存起来,然后可以切换到master分支进行打包。

打完包后,切回之前的分支,然后:

git stash pop
  • 注意:没有add过的文件是不会被stash起来的,因为git会忽略他们,如果要把这部分文件也stash,加-u参数
git satsh -u

高级10:branch删除之后才想起来有用?

reflog:引用的log

它会显示HEAD的移动记录。

在这里插入图片描述

从图中看出,最后一次是从branch1转移到master,所以前一个commit就是在branch1被删除之前的位置,也就是第二行的c08de9a。

切回到c08de9a,重新创建branch1,就可以找回。

git checkout c08de9a
git branch -b branch1
  • 注意,被删除的commit会在一定时间后被回收,所以要及时找回,不然就找不到了。

查看其他引用的reflog

git reflog master

其他知识点

tag:不可移动的branch
cherry-pick:把选中的commits一个个合并进来
git config:Git的设置
Git Flow:复杂又高效的工作流
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!