Git 学习二:Idea 中 Git 使用

Git 学习二:Idea 中 Git 使用

  • Git 学习二:Idea 中 Git 使用
    • 特别重要
    • 颜色代表的含义
    • 简述
    • 常用操作
    • 补充点
      • Git 的 stage对象以 hunk 为单位

参考
IntelliJ-IDEA和Git、GitHub、Gitlab的使用(五)
解决 Git 的 Merge Conflict

Idea 默认已集成 Git 插件(插件不是客户端,所以 Git 客户端还是由用户来下载安装的)。

特别重要

提交项目之前先对项目进行更新,此项特别重要,如果不进行更新,别人有项目提交到服务器上,那么你的项目将会提交不上去,使用git解决冲突会比较麻烦,即使你解决了冲突,但是有时候不注意会冲掉别人写的代码。

操作:项目右键点击——Git——Repository——Pull.

颜色代表的含义

  • 灰色:版本控制已忽略的文件
  • 红色:未加入版本控制
    需 Add 到 stage(待提交区域)。
  • 绿色:加入版本控制,未提交
    需提交到本地 Repository。
  • 蓝色:加入版本控制,已提交,有改动
  • 白色:加入版本控制,已提交,无改动

简述

Git 学习二:Idea 中 Git 使用_第1张图片

  1. 工作区有一个隐藏目录.git,这个不算工作区,而是Git的版本库。
  2. Git 的版本库(Repository)里存了很多东西,其中最重要的就是称为 stage(或者叫index)的 暂存区 ,还有Git为我们自动创建的第一个分支master,以及指向master的一个指针叫HEAD。
  3. 我们把文件提交到 Git 版本库,是分两步执行的。
    第一步:git add 就是把文件添加到暂存区;

    为什么要先添加进暂存区?
    要解释这个问题,首先得明白暂存区为什么要存在。
    我们了解的 SVN 相对于第一代源代码管理工具如VSS、CVS有几个显著的区别,其中最重要的特性之一就是原子性提交,每一个提交都是由多个文件的修改组成,而且这个提交是原子性的,要么这些修改全部成功,要么全部失败。原子性提交带来的好处是显而易见的,这使得我们把项目整体还原到某个阶段或者时间点变得极为简便,就这一点SVN就完虐VSS等源代码管理工具。
    Git 继续了这一优良传统,但 Git 在命令行下选择要提交的多个文件是有点麻烦的(SVN 是使用GUI 图形管理工具操作,多选只是多选一些复选框就可以了)。为此,Linus 引入了一个暂存区的环节,暂存区里可以随意的将各种文件的修改放进去,这样我们就可以用多个指令精确的挑选出我们需要提交的所有修改,然后再一次性的(原子性的)提交到版本库,问题就完美的解决了。
    引入暂存区不仅可以分批提交文件,还方便进行快照,便于回退。
    最佳实践
    1、做了阶段性修改,但是还不能做一次递交,这时先 git stage 一下
    2、如果有问题,可以随时 checkout 回退
    3、递交之前,使用 git status,git diff HEAD 仔细查看是否需要的递交
    4、git commit -a ,保证递交了所有内容

    第二步:git commit 就是把暂存区里的文件提交到当前分支;

    可以使用 git commit -a 命令,跳过 git stage 这个命令,直接提交。

  4. 撤销修改
    场景1:当你改乱了工作区某个文件的内容,想直接丢弃工作区的修改时,用命令git checkout – file
    场景2:当你不但改乱了工作区某个文件的内容,还添加到了暂存区时,想丢弃修改,分两步,第一步用命令git reset HEAD file,就回到了场景1,第二步按场景1操作。
    场景3:已经提交了不合适的修改到版本库时,想要撤销本次提交,git reset HEAD

常用操作

帮助

man git add

添加进暂存区、从暂存区中回退

// 添加
方法一(命令):git stage
方法二(命令):git add
方法三(工具):Git->Add // 效果等同方法二

// 回退
方法一(命令):git rm --cached <file> // 从暂存区直接删除对应文件
方法二(命令):git reset head // 将本地仓库的文件替换到Stage区里相应的文件
方法三(工具):文件右击->Git->Repository->Reset HEAD...->Reset(Reset Type默认为Mixed) // 效果等同方法二

subversion 中的 svn add 动作是将某个文件加入版本控制,而 git add的意义完全不同。
git add:将修改的文件添加进暂存区,但这是一个容易引起疑问的命令,后续版本中修改为git stage。

比较文件差异

// 显示当前工作区的文件和stage区文件的差异
git diff

// 显示stage区和HEAD的文件的差异
git diff --staged
// 或
git diff --cached

// 显示工作区和上次递交文件的差异
git diff HEAD

还原文件
reset 和 checkout的区别

// 当文件加入了 stage 区以后,如果要从stage删除,则使用 reset,此时工作区的文件不做任何修改。如下(这个命令是 git stage hello.py 的反操作)
git reset hello.py

// 当文件加入了 stage 区以后,后来又做了一些修改,这时发现后面的修改有问题,想回退到stage的状态,使用 checkout 命令
git checkout hello.py

提交

// 提交 stage 区的文件
git commit -m ""

// 提交所有修改(未进stage的添加进stage),相当于git add和git commit -m的组合技,前提是被改动文件已经是tracked
git commit -am ""

补充点

Git 的 stage对象以 hunk 为单位

参考
一个hunk就是一个diff中一段连续的改动,一个diff由一个或多个hunk所组成,而hunk的大小是可以控制的,最小单位是一行,也就是说你可以把diff一行一行的添加到stage中,然后分多次分别commit。
这个功能有毛用?一个理想的开发过程是每个commit仅包含一个feature或bugfix。为什么要这样?当你需要bisect找bug时,或revert某个commit时,或cherry-pick某个commit到其它分支时……就会发现保持commit干净的重要性。
但不幸的是绝大多数人都有在一个commit中包含多项无关改动的倾向(包括我自己),至于为什么会这样,我也不知道,这里也不讨论,相信各位有开发经验的同学都会在现实中遇到无数这种实例,结果最后得到的通常是一串混乱不堪的历史。
但git带来一个不一样的故事:它支持hunk。所以现在我工作时常见的一个典型场景是这样:1. 开始开发功能A2. 开发A的过程中发现有个小bug B,只需要改动几行就能搞定,于是顺手改掉3. 功能完成了,先把B所属的hunk stage起来,然后commit4. 再把剩余的跟A相关的所有hunk stage起来,然后commit最后得到一个干净的历史。
基于hunk的具体用法请见git add -p,但悲剧是这个内置的功能太不好用了,所以我基本上通过第三方工具来用。
命令行的话强烈推荐tig这个基于curses的UI,vim的话就fugitive,其它GUI工具里我记得SourceTree好像也是支持的。

你可能感兴趣的:(工具,Git)