git


Git是我们现在比较常用的版本管理系统,学会Git是我们每一位开发者的必备技能。

所以本篇我们主要来总结一下git的常用命令及使用的基本流程。

安装Git【比较简单,不多赘述】

要使用Git,第一步就是要先安装Git,安装完成后我们可以通过 git –version 来查看git的版本号;

  git --version

因为Git是分布式版本控制系统,所以我们在安装完成后,需要设置一下提交代码时的用户信息

  git config --global user.name '张佳丽'
  git config --global user.email 'zhang.jiali@datatom.com'

注意 git config 命令的 –global 参数,用了这个参数,表示你这台机器上所有的 Git仓库 都会使用这个配置,当然也可以对某个仓库指定不同的用户名和Email地址。

可以通过 git config –list 来查看当前的git配置

在工作过程中我们每天都会使用Git。一般来说日常使用只要记住6个左右就可以了,但是要熟练使用,差不多要记住60-100个命令

几个专用名词:

  • Workspace:工作区
  • Index / Stage:暂存区
  • Repository:仓库区(本地仓库)
  • Remote:远程仓库

下面重点介绍一下我们在项目开发过程中Git的一些常用命令及一些可能的问题,其他git相关的内容大家可以根据自己的情况再去近一步学习:

新建代码库:我们最常用的是git clone,将代码从代码仓库中克隆到本地;

    <!-- 在当前目录新建一个git代码库 -->
    git init

    <!-- 新建一个目录,将它初始化为git代码库 -->
    git init [project-name]

    <!-- 从代码仓库中下载一个项目以及整个代码历史 -->
    git clone [url]

git clone 有两种方式:

  1. HTTP
  2. SSH

新建分支:我们要求通过分支的方式来开发。比如每次开发新功能,修复bug等都应该新建一个单独的分支来开发

    // 新建一个分支,并切换到该分支
    git checkout -b feature-search

    // 相当于
    // 新建一个分支,但仍停留在当前分支
    git branch feature-search
    +
    // 切换到指定分支,并更新工作区
    git checkout feature-search

我们可以使用git branch来查看所有本地分支;(git branch -a查看所有本地分支和远程分支)

注意事项

    // 新建一个分支,与指定的远程分支建立追踪关系
    git branch --track [branch] [remote-branch]

    // 建立追踪关系,在现有分支与指定的远程分支之间
    git branch --set-upstream-to=origin/<remote-branch> branch

提交分支:代码修改后,就可以提交分支了,具体的步骤:

    // 显示所有有变更的文件
    git status
    // 添加所有变更文件到暂存区
    git add .

    // 添加指定文件到暂存区
    git add [file1] [file2] ……

    // 将文件从暂存区移除
    git reset HEAD [file1]
    // 重置暂存区的指定文件,与上一次commit保持一致,但工作区不变
    git reset [file]
    // 重置暂存区与工作区,与上一次commit保持一致
    git reset --hard
    // 重置当前分支的指针为指定commit,同时重置暂存区,但工作区不变
    git reset [commit]

    // 提交暂存区到仓库区
    git commit -m [message]

    // 新建一个commit,用来撤销指定commit
    // 后者的所有变化都将被前者抵消,并且应用到当前分支
    git revert [commit]

与主干同步:分支的开发过程中,要经常与主干保持同步。

一旦远程主机的版本库有了更新(Git术语叫做commit),需要将这些更新取回本地,这时就要用到git fetch命令;

    // 将某个远程主机的更新,全部取回本地。
    git fetch <远程主机名>
    // eg: git fetch origin

    git merge origin/master
    git rebase origin/master

git fetch命令通常用来查看其他人的进程,因为它取回的代码对你本地的开发代码没有影响。

默认情况下,git fetch取回所有分支(branch)的更新。如果只想取回特定分支的更新,可以指定分支名。

    git fetch <远程主机名> <分支名>
    // eg: 取回origin主机的master分支。
    git fetch origin master

所取回的更新,在本地主机上要用”远程主机名/分支名”的形式读取。比如origin主机的master,就要用origin/master读取。

取回远程主机的更新以后,可以在它的基础上,使用git checkout命令创建一个新的分支。

    // 在origin/master的基础上,创建一个新分支。
    git checkout -b newBrach origin/master

也可以使用git merge命令或者git rebase命令,在本地分支上合并远程分支。

    // 在当前分支上,合并origin/master
    git merge origin/master
    git rebase origin/master

可以使用 git rebase –abort 丢弃合并

在git merge或者git rebase之前可以先使用git diff 来查看变更;

    git diff origin/master

合并commit:分支开发完成后,可能会有多个commit,但是合并到主干的时候,希望只有一个(或者最多两三个)commit,这样不仅清晰,也容易管理。

  • 对于 commit 的修改可以使用 git commit -amend 修改下 commit 信息;
      // 使用一次新的commit,替代上一次提交
      // 如果代码没有任何新变化,则用来改写上一次commit的提交信息
      git commit --amend -m [message]
    
  • 那么怎样才能将多个commit 合并呢?这就要用到git rebase命令。

    可以使用 git log –oneline / git log –graph –pretty=oneline –abbrev-commit 查看 commit 信息。

      <!-- 如果想合并最近四次的提交: -->
      git rebase -i HEAD~4
    

    git rebase命令的i参数表示互动(interactive),这时git会打开一个互动界面,进行下一步操作;

    上面的互动界面,先列出当前分支最新的4个commit(越下面越新)。每个commit前面有一个操作命令,默认是pick,表示该行commit被选中,要进行rebase操作。

    4个commit的下面是一大堆注释,列出可以使用的命令。

      pick:正常选中
      reword:选中,并且修改提交信息;
      edit:选中,rebase时会暂停,允许你修改这个commit(参考这里)
      squash:选中,会将当前commit与上一个commit合并
      fixup:与squash相同,但不会保存当前commit的提交信息
      ……
    

    上面这6个命令当中,squashfixup可以用来合并commit。先把需要合并的commit前面的动词,改成squash(或者s)。

    • 把上图中第2,3行的动词改为s;

    这样一改,执行后,当前分支只会剩下两个commit。第二行和第三行的commit,都会合并到第一行的commit。提交信息会同时包含,这三个commit的提交信息。

    • 如果将第三行的squash命令改成fixup命令

    运行结果相同,还是会生成两个commit,第二行和第三行的commit,都合并到第一行的commit。但是,新的提交信息里面,第三行commit的提交信息,会被注释掉。

    使用git rebase合并多次commit信息有什么好处?

    • 可以避免将错误的 commit 信息提交到代码仓库
    • 比如这次的代码提交你需要合并到其他分支时,只需要cherry-pick 一次就可以,否次需要cherry-pick多次;而且时间长了容易遗忘【很难记得一个功能分为几次提交的】
    1. 使用 rebase 修改 commit 只在本地分支发生
    2. 本地分支 push 到服务器仓库上前都应该先 git rebase origin (branch) 保证拉取最新代码。
    3. 禁止使用 git push –force 覆盖服务器上的提交历史。

推送到远程仓库:合并commit后,就可以推送当前分支到远程仓库了。


  // 正常的话使用
  git push


  // 如果使用了git rebase可能需要强制推
  // 需要谨慎使用
  git push --force   
  git push --force origin test
  // git push命令要加上force参数,因为rebase以后,分支历史改变了,跟远程分支不一定兼容,有可能要强行推送。


  // 如果远程仓库没有这条分支的话,需要用以下命令来推
  git push --set-upstream origin test
  git push -u origin test

Merge Request 流程

提交到远程仓库以后,就可以发出 Pull Request 到master分支,然后请求别人进行代码review,确认可以合并到master。

常见问题:

1.git clone 有时会遇到问题:fatal: unable to access

解决办法

  1. 通过ssh方式链接远程仓库获取代码——创建ssh key $ ssh-keygen -t rsa -C “your email address” – 填写gitLab邮箱 连续按按三个Enter ,ssh key创建成功 注意:生成id_rsa这是私钥文件。id_rsa.pub这是公钥文件。
  2. 将公钥添加到gitLab账户的key中即可。
  3. 根据git的ssh链接地址clone

2.可能需要同时处理多项任务,比如:在feature-search分支开发新功能的途中,有一个紧急bug需要在两个小时内修复完成,而新功能可能还需要1天或者更长的时间,没有办法立马提交。这个时候怎么办?

可以使用git stash把当前工作现场“储藏”起来,等以后恢复现场后继续工作:

我们开发新功能或者修复bug都是需要新开一条分支的! 解决办法

  1. 使用 git stash 将feature-search开发到一半的代码暂存一下;
  2. 然后用git status查看工作区,就是干净的(除非有没有被Git管理的文件),因此可以放心地创建分支来修复bug。
  3. 接着确定要在哪个分支上修复bug,假定需要在master分支上修复,就从master创建临时分支:eg:bugfix-0705;
  4. 修复完bug后切回开发到一半的分支继续开发,可以使用git status查看工作区,确保工作区是干净的。接着用git stash list命令查看;
  5. 可以通过两种方式来恢复:
    • 是用git stash apply恢复,但是恢复后,stash内容并不删除,你需要用git stash drop来删除;
    • 用git stash pop,恢复的同时把stash内容也删了:
  6. 可以多次stash,恢复的时候,先用git stash list查看,然后恢复指定的stash,用命令:git stash apply stash@{0}

3.在master上修复了bug后,我们要想一想,这个bug其实在多条分支上都是存在的。是否需要重复修复、重复提交?

我们只需要将指定的提交合并过来,而不是整条代码线; 解决办法 可以用git cherry-pick 命令,把指定的提交“复制”到当前分支,避免重复劳动。

注意 这两个commit只是改动相同,但是是两个不同的commit。根据commit ID可以看出;

4.git commit 的提交信息

    feat: 新功能(feature
    fix: 修补bug
    docs: 文档(documentation
    style: 格式(不影响代码运行的变动,比如格式化了代码、if-else优化)
    refactor: 重构(即不是新增功能,也不是修改bug的代码变动)
    test: 增加测试
    chore: 构建过程或辅助工具的变动

5.git pull

    使用git pull时建议使用git pull --rebase
    git pull --rebase

6.要利用好git status和git log

在项目开发的过程中要随时使用git status和git log;

  • 要随时掌握工作区的状态,使用git status命令。
  • 如果git status告诉你有文件被修改过,用git diff可以查看修改内容。