文章

git学习笔记

配置Git

Git config 官方多语言文档

  • git config --global core.editor "code --wait": 指定vscode作为全局编辑器.
  • git config --global diff.tool vscode: 设置通过vscode查看文件变更.
  • git config --global difftool.vscode.cmd "code --wait --diff $LOCAL $REMOTE": 配置git打开vscode的命令参数.
  • git config --global -e: 使用全局编辑器编辑配置文件.
  • git config --global core.autocrlf input: 配置换行符

    windows的换行符是\r\n, 而mac是\n, 如果配置错误就会在使用git时出现很多不必要的麻烦.

    • Mac: core.autocrlf input
    • Win: core.autocrlf true

    通常在git安装时会自动配置, 知道原理即可.

  • git config --global init.defaultBranch <name>: 设置git默认分支名称, 未设置默认为master, 但是初始化git时会有额外的提示信息.
  • git config --global alias.lg "log --pretty=format:'%an -> %h'": 为git命令创建别名, 可以通过别名将复杂的git命令和参数进行简化.

    pretty fromat相关文档

    一个自用的简略信息:%Cgreen%an<%ae>%Creset->%Cblue%h%Creset@%as:%Cred%s%Creset

  • git config --global core.pager=cat: 设置git命令的输出分页器, 默认使用less, 会将结果单独显示在一个屏幕中, 需要按q才能退出, 原始终端则没有内容. 改为cat则直接在当前命令行输出, 根据个人偏好配置即可.

sep

Git 命令行工具

仓库管理

  • git init: 初始化git目录, 自动创建.git文件夹.
  • git status: 查看当前git状态. 也可结合参数-s显示简略信息.
  • git add [option]: 将变更内容添加到缓存区.
  • git commit -m"commit message": 提交到本地仓库.

    如果设置了git的全局编辑器, 可以直接使用git commit, 此时会使用指定的编辑器打开一个文本文件, 可以更为方便的输入提交描述.

  • git commit -am "commit message": 跳过缓存, 直接将全部修改提交到本地仓库.

文件操作

  • git ls-files: 显示git管理的文件.
  • git rm [file]: 在git和本地同时删除指定文件.
  • git rm --cached [file]: 仅删除git缓存的文件, 本地文件不受影响.
  • git mv [file]: 在本地和git中同时移动或者重命名文件.
  • git restore [file]: 将本地已有索引的文件恢复至修改前的状态.
    • --staged: 将缓存区的内容回复至之前的状态.
    • --source=[HEAD~n | id] filename: 将修改或删除的文件恢复到之前提交的版本.
  • git clean: 删除所有未创建索引的内容, 危险操作, 需要配合参数执行.
    • -f: force强制执行
    • -d: 包含文件夹

源码管理

  • git diff: 显示缓存区与工作区的变动
    • --staged: 查看缓存区的变动内容.
    • HEAD~2 HEAD [filename]: 查看最近3次的全部或特定文件的变化.
  • git log: 显示提交记录
    • --oneline: 显示提交记录摘要
    • --reverse: 逆序显示
  • git show: 显示最后一次提交的变更内容
    • HEAD~n: HEAD代表最后一次提交, n表示向前数n次, 比如HEAD~n
    • 也可以通过log查看提交id, 通过指定id查看提交内容.
    • HEAD:path/to/file: 查看特定文件的变动.
    • HEAD --name-status: 查看更改的文件.
  • git checkout [id]: 将工作区恢复至指定的快照id.
    • HEAD~n: 向前数n个快照.
    • master: 设置为最新的快照.

查找bug

当一个快照出现问题, 而这个问题有可能是由于之前的快照索引的, 那么诸葛快照查找就会非常麻烦.

为了这种情况, git 提供了一个强大的工具, bisect. bisection的缩写, 本质就是采用二分法查找出错的快照.

  1. git bisect start: 开始二分查找
  2. git bisect bad: 标记当前快照有问题, 通常在master快照下执行
  3. git bisect good [id | HEAD~n]: 指定之前的一个确定没问题的快照, 此时bisect会自动帮助我们在不同的快照之间进行切换, 用以检查错误.
  4. git bisect good: 标记当前检查的快照正常, bisect会自动切换至下一个快照
  5. git bisect bad: 标记该快照为异常快照
  6. git bisect reset: 退出bisect模式.

设置快照标签

  • git tag v1.0.0: 设置当前快照的标签为v1.0.0
  • git tag empty d873716 -m "empty project": 为指定id的快照添加empty标签, 同时设置标签信息.
  • git checkout empty: 根据标签checkout
  • git tag -n: 列出所有标签和标签信息.
  • git tag --points-at <id>: 列出指定或者当前快照的标签
  • git tag -d [tagname]: 删除标签

sep

.gitignore文件

在根目录下建立.gitignore文件用以配置忽略版本控制的文件.

1
2
3
logs/       # 忽略logs目录
main.log    # 忽略指定文件
*.log       # 忽略匹配文件

对于已经加入git索引的内容不会受到.gitignore文件的影响.

需要通过git rm --cached命令手动将其在索引中删除.

.gitignore 模板仓库

sep

Git可视化软件

Sourcetree: 完全免费, 仅支持Windows和Mac.

preview

GitKraken: 针对开源软件项目免费. UI是相当的舒服~~

preview

sep

Git 分支管理

git的分支是一个指向master快照的指针, 并不会创建新的文件系统, 所以不会像svn一样产生额外的消耗.

  • git branch bugfix: 创建名为bugfix的分支
  • git branch: 列出所有分支
  • git switch bugfix: 切换到bugfix分支
  • git switch -C bugfix: 创建并切换到bugfix分支
  • git branch -m bugfix bugfix-somebug: 重命名分支
  • git branch -d bugfix-somebug: 删除指定分支, 如果分支存在未合并的内容则无法删除. 在确定删除的情况下可以使用-D强制执行.
  • git branch --merged: 显示已经合并的分支
  • git branch --no-merged: 显示尚未合并的分支

确定两个分支之间的不同

  • git log master..bugfix-somebug: 显示分支之后的提交内容.
  • git diff master..bugfix-somebug: 显示两个分支之间的差异.

    如果当前已经在master分之下, 可以省略master..

  • git diff --name-only bugfix-somebug: 显示有差异的文件.
  • git diff --name-status bugfix-somebug: 显示有差异的文件状态.

    比较实用的命令, 可以创建两个别名, 比如dno,dns

通过stash缓存变动内容

在工作区发生了变动, 并且没有进行提交时, 如果需要切换到其他的分支, 可以将变动内容暂存以备之后使用.

  • git stash push -m "stash message": 将工作区的变动内容移至暂存区.
    • 如果工作区包含为索引的内容, 可以使用-am参数, 即--all -m.
  • git stash list: 列出暂存区索引.
  • git stash show n: 显示第n条暂存内容的变更项.
  • git stash apply n: 取回暂存区的第n个索引.
  • git stash drop n: 删除第n项
  • git stash clear: 清空暂存区

合并分支

合并分支大致分为两种情况:

  1. 在分支修改完成后, 主分支没有发生变化, 此时可以直接让主分支指向当前分支. 成为Fast Forward. ff

  2. 在分支代码修改完成后, 主分支有其他的提交, 此时则需要重新建立一个合并提交. 3wf

对于第一种情况来说, 合并分支非常简单, 只需要在master分支下执行合并命令即可;

1
git merge bugfix-somebug

如果不希望使用Fast Forward可以添加参数--no-ff. 这样当前的master就会和分支合并为一个新的快照.

有些公司会禁用FF合并, 因为这会让项目的演化信息丢失, 整个项目的研发路线成为一条支线. 如果在应用分之后希望退回之前的状态, 那么就需要找到建立分支时的快照.

但不使用FF的情况下无论何时想要取消合并只需要回退一步就可以了.

也可以通过git配置禁用FF从而省略关键字:

1
2
git config merge.ff false # 当前工作区禁用
git config --global merge.ff false # 全局禁用

还有一种不太常用的合并方式, git merge --squash branch. 直译压缩合并.

会将指定分支中的变动内容加入到当前分支, 可以直接使其为对当前分支的修改. 但本质上并没有将分支合并到主分支上.

因此只适用于较小变动的分支, 且应当在合并操作之后将分支删除.

因为虽然压缩合并已经将分支内容写入了主分支内, 但是通过git branch --merged命令查看已经合并的分支时不会显示压缩合并的分支. 这会产生歧义, 无法判断该分支是否已经被正确处理了.

解决合并冲突

当合并两个分支时, 如果他们对同一个文件进行过修改提交时就会出现冲突(conflicts). 此时通过git status查看产生冲突的文件, 手动选择需要保留的代码并提交即可.

在使用GitKraken一类功能强大的可视化工具时可以很好的解决合并分支和冲突问题.

但GitKranken只针对开源项目免费.

也有一些免费的合并工具, 比如P4Merge

可以通过git全局设置来指定默认的合并工具

1
2
git config --global merge.tool p4merge
git config --global mergetool.p4merge.path "/Applications/p4merge.app/Contents/MacOS/p4merge"

配置完成后, 当出现冲突时就可以直接使用git mergetool启动工具.

如果希望中止合并, 可以直接使用命令git merge --abort.

p4merge会自动为冲突文件创建副本, 而git则会询问这一副本文件.

可以在.gitignore文件中添加备份文件*.orig

或直接通过全局配置禁用备份:

1
git config --global mergetool.keepBackup false

撤销提交

如果希望撤销一个提交, 可以通过命令 git reset [mode] HEAD~1完成.

撤销命令存在三种模式:

  • --soft: 仅修改快照指针, 本地缓存(stage)和工作区不受影响
  • --mixed: 修改快照指针, 同时将指向的快照版本放入本地缓存, 工作区不受影响.
  • --hard: 修改快照指针, 同时将快照放入工作区, 相当于checkout.

也可以通过git revert HEAD指令进行回退.

Rebase 重建分支

在分支创建后, 如果主分支有新的提交, 可以将分支进行重建操作, 以使项目呈线性的提交历史.

在分支下执行指令git rebase master即可.

rebase

rebase会修改项目的提交历史, 仅在本地, 不要在团队项目中使用.

本文由作者按照 CC BY 4.0 进行授权