Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

git使用总结 #1

Open
Gesangs opened this issue Aug 7, 2018 · 1 comment
Open

git使用总结 #1

Gesangs opened this issue Aug 7, 2018 · 1 comment

Comments

@Gesangs
Copy link
Owner

Gesangs commented Aug 7, 2018

前言

版本控制系统:在文件的修改历程中保留修改历史,让你可以方便地撤销之前对文件的修改操作

git是分布式版本控制系统,包含一个中央仓库和多个本地仓库。中央仓库的主要任务是同步团队代码,保存版本历史的工作转交到了每个团队成员的本地仓库中。

概念

  • .git
    这个文件夹保存了所有版本信息,是git的工作目录

  • commit
    保存了文件的改动信息,有多个引用可以指代某个commit
    • sha-1码(下图中commit后的那串字符),几乎不可能出现的重复,所以取开头一段指代也是可以的
    • 分支名,包括默认分支master,和自主创建的分支,都是某个 commit的引用
    • HEAD,总是指向当前commit,且唯一
    • origin/master指代远程中央仓库的master分支
      origin/HEAD指代远程仓库中的HEAD

git_commit_id

1534236310474
如图中所示,HEAD和master都指向7428c141535这个commit

  • 分支branch
    可以理解为一个指针,对某个commit的引用,是从初始 commitbranch 所指向的 commit 之间的所有 commits 的一个「串」,或者称为路径,且这条路径不唯一。
    master本质也是一个分支,为创建仓库时第一次commit默认创建的分支,自动指向了第一次commit

  • HEAD
    一个总是指向当前commit(最新)的指针,且唯一,总是跟随着当前commit的移动而移动
    在每次提交时HEAD都会自动向前移动到最新的 commit

基本操作指令

  • git add
    把所选文件的改动(如果有的话)添加到缓存区,.代表目录下的所有文件,每次有了新的改动提交前都要执行一次。

  • 提交 git commit
    git commit -m+ 'msg' 把文件缓存提交到本地仓库并附加上这次commit的描述,然后将HEAD指向这个commit
    总是基于HEAD指向的commit进行提交

  • 拉取 git fetch
    把远程的中央仓库的内容(版本信息,commit等)同步到本地仓库。

  • 分支 git branch
    git branch+name 创建分支
    本质上是为当前commit(即HEAD指向的commit)创建一个引用
    创建后执行git push origin master把分支推送到远程仓库,orgin是创建时中央仓库的默认名字
    git branch -d删除这个引用,但不会删除commit,被遗留的无法追溯的commit会被自动回收
    未被合入masterbranch需要使用git branch -D删除。

  • 签出 git checkout
    本质是移动HEAD指向。checkout 的意思就是把某个 commit 作为当前 commit,把 HEAD 移动过去,并把工作目录的文件内容替换成这个 commit 所对应的内容
    git checkout+branchName 切换分支
    git checkout -b+branchName 创建分支并切换到该分支
    git checkout -b + new branchName +origin/master 基于远程 master 分支切出一个新分支
    git checkout+ . 清空暂存区

  • 合并 git merge+targetCommit
    指定一个 commit,把它合并到当前的 commit 来。
    具体来说就是,从目标 commit 和当前 commit (即 HEAD 所指向的 commit)分叉的位置起,把目标 commit 的路径上的所有 commit 的内容一并应用到当前 commit,然后自动生成一个新的 commit

  • 变基 git rebase
    rebase 的意思是,给你的 commit 序列重新设置基础点(也就是父 commit)。展开来说就是,把你指定的 commit 以及它所在的commit串,以指定的目标 commit 为基础,依次重新提交一次
    git checkout example => git rebase master => git checkout master => git merge example 这3步操作就是切换到example分支,然后把从切出该分支开始的第一个commit到当前(最后一个 )commit组成的commit串,以master指向的commit为基础,再重新提交一次,然后切回master执行一次merge就可以把example分支的修改信息合入master分支。请看图:
    rebase
    merge

图片出自掘金小册《Git 原理详解及实用指南》


  • rebasemerge 的比较
    • git rebasegit merge有异曲同工之妙,结果都是合并了两个分支的修改信息。
    • 区别(以把example分支的修改信息合并到master分支上为例):
      • rebase是站在example分支上合到master分支去,而merge是站在master分支上把example分支合进来。所以区别之一就是站在的基准不同。
      • merge会把分支上的commit合并为一个commit再合进来,而rebase正常操作是把commit依次合进去,会有多次commit的修改信息,只要加入-i参数也可以和merge一样合并为一个commit
        git rebase -i master之后会进入提交信息界面(待补图),只要把下图中要合并的commit前面的pick改为f,然后保存退出即可把置为fcommit合入被pickcommit中。

  • 拉取 git pull
    本质是先git fetch同步信息到本地,然后在执行git merge把新增的commit合并到当前commit中。

  • 冲突 conflict
    在合并commit的过程中,git本身自带一定的自动合并能力,但是当两个commit修改了同一个地方,git就傻傻分不清楚以哪个commit的修改信息为准了,这时就产生了冲突,需要手动操作了。
    • merge中的冲突
      修改冲突 => git add . => git commit 即可解决冲突并成功合并
      在发生冲突时使用git merge --abort即可放弃这次合并,恢复到合并前的状态。
    • rebase中的冲突
      修改冲突 => git add . => git rebase --continue 即可解决这次冲突(可能需要解决多次冲突)
      同样使用git rebase --abort可放弃并恢复到变基前。


Feature Branching

接下来先描述这个流行的团队协作模型

  • 任何新的功能featurebug 修复全都从主分支(一般为master)中切出一个 branch 来写;
  • branch写完后,合并到 master,然后删掉这个 branch

举个例子
  1. 为项目A新增一个商品详情页面,拉取项目A最新内容到本地,新建一个detail分支进行开发
git pull
git checkout -b detail
  1. 开发。经过十几个commit终于开发完成
git commit -m 'commit1'
git commit -m 'commit2'
......
git commit -m 'commit10'
git commit -m 'commit11'
  1. 把开发完成的detail分支推到中央仓库,并告诉同事分支名,帮忙review一下代码
git push origin detail
  1. 同事刚好有空,于是拉取你的分支review,并给予你反馈
# 同事的电脑:
git pull
git checkout detail
  1. 得到同事的反馈后,会有两种情况
  • 若review过程没有问题,那就可以把detail分支合入到master中,然后推送到中央仓库并删除该分支
git pull
git checkout detail
git rebase -i master
git checkout master
git merge detail
或者
git pull
git checkout master
git merge detail
git push
git branch -d books
git push origin -d books # 用 -d 参数把远程仓库的 branch 也删了
  • 若review时发现了问题,就进行修复commit,然后再从第3步开始,提交=>review,直到得到同事的pass,然后合入master
git commit -m 'fix bug'
......
review
  1. 新增功能开发结束
    至此,一个工作流就描述完了。在这个过程中,团队的所有成员都同时进行开发,互不干预,所有分支在未得到pass之前都不会合入主分支,从而也保证了主分支的正常运行。


进阶操作指令

  • git stash 储藏
    假设这样一个场景。你正在A分支开发一个新功能,此时测试报了一个紧急bug要你立马修复,但暂存区内修改了很多文件又不想提交上去,此时你就可以使用git stash指令把暂存区内的内容储藏到一个未完结变更的堆栈中,随时可以重新应用。然后你就可以切到B分支,等修复完成后,再切回A分支使用git stash apply指令恢复到原本的样子。
# 带上-u参数会把未add过的改动也stash起来
git stash -u 
git checkout B
......
git checkout A
git stash apply
或
git stash pop
  • 撤回rebase
    找到rebase前的commit的sha-1码:git reflog
    然后再git reset --hard sha-1

  • 修改commit
    commit完你就发现写错了,那这个时候就可以新写一个commit修改,然后在commit的时候加上--amend参数,这个新的commit就会替换掉刚才已经提交了的写错了的commit
    git commit --amend

  • 删除commit
    同样是刚commit完你就发现写错了,但是没有修改的价值了,不如删除了重写过,那这个时候就可以
    git reset --hard HEAD^来撤销这个commit,本质上就是把指向最新commitHEADbranch
    一同移到前一个commit

  • 用a分支覆盖b分支
    git push origin a:b -f

^表示位移,HEAD^指的是HEAD指向的commit的前一个commit,几个^就是前几个
~同样是位移,HEAD~2指的是前两个

  • checkoutreset的比较
    乍一看这两个指令都是移动指向,其实checkout只是移动了HEADbranch还留在原地,而reset是带着HEADbranch一起移动的

  • git cherry-pick
    选择某个节点,合入该分支中。
    假设当前有a、b两个分支。a分支的改动巨大,当前已合入master,b分支改动少量,还未合入master,若此时将b分支合入master,将产生大量冲突。这时可从现有master中切一个c分支,然后利用cheery-pick将b分支中的commit(可先合并b分支中的commit)合入c分支中,再把c合入master中

  • ...... (欢迎补充更多实用git命令)

  • .gitignore
    排除不想被管理的文件和目录,把文件路径写入改文件即可

This was referenced Aug 23, 2018
@liyatang
Copy link

image
git push origin detail 和 git checkout detail 能用?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants