技术成就梦想

代码如诗

git入门大全

2017年8月13日 未分类 0

前言

以前写个一个git小结,但是实际上并不够用。于是结合实际工作上碰到的一些情况,参考了一些资料,重新总结了一下。目标是在日常工作中不用再去查阅其他的资料了,如果有什么遗漏或者错误的地方,请评论指出!

基本概念

Workspace:工作区

Index / Stage:暂存区

Repository:仓库区(或本地仓库)

Remote:远程仓库

文件几种状态

  • untracked:git未跟踪的文件,新增的文件未 git add 就会处于这种状态
  • not staged:被索引过又被修改了的文件
  • staged:通过 git add后即将被提交的文件

创建新仓库

# 在当前目录
git init

配置

# 显示当前的Git配置
git config –list

# 编辑Git配置文件
git config -e [–global]

# 设置提交代码时的用户信息
git config [–global] user.name "example"
git config [–global] user.email "example@gmail.com"

# 配置自动换行,提交到git时自动将换行符转换为lf
git config --global core.autocrlf input

# 配置密钥
ssh-keygen -t rsa -C example@gmail.com # 生成密钥
ssh -T git@github.com # 测试是否成功

# 配置别名,--global 表示全局配置
git config --global alias.st status

git config --global alias.co checkout

git config --global alias.br branch

git config --global alias.ci commit

git config --global alias.lg "log --color --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit"

检出仓库

# 创建一个本地仓库的克隆版本:
git clone /path/to/repository

# 如果是远端服务器上的仓库:
git clone username@host:/path/to/repository

# 克隆到自定义文件夹:
git clone username@host:/path/to/repository my-cloned-repo

新建仓库常见流程

# 初始化
git init

# 获取状态
git status

git add README.md

git commit -m "message"

# 连接远程仓库
git remote add origin git@github.com:example/test.git

# 推送内容到远程仓库的同时设置默认跟踪分支
git push -u origin master

gitignore

vim .gitignore
!为模式取反

*.a
!lib.a

添加、删除

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

# 添加指定目录到暂存区,包括子目录
git add [dir]

# 添加当前目录的所有文件到暂存区,.或*代表全部添加
git add .

# 添加每个变化前,都会要求确认
# 对于同一个文件的多处变化,可以实现分次提交
git add -p

# 删除工作区文件,并且将这次删除放入暂存区
git rm [file1] [file2] ...

# 停止追踪指定文件,但该文件会保留在工作区
git rm --cached [file]

# 文件重命名,并加入暂存区
git mv [file-original] [file-renamed]

# 通配符批量移动
git mv *.html src/

提交

git commit -m "message"

# 补提交文件,提交时漏掉了某些文件时不应该再单独提交一次
git commit --amend

# 覆盖提交日期,不知道有啥实际用途
git commit -m "message" --date "2017-01-01 00:00:00"

branch

# 列出所有本地分支
git branch

# 新建一个分支,但依然停留在当前分支
git branch [branch-name]

# 新建一个分支,并切换到该分支
git checkout -b [branch]

# 切换到指定分支,并更新工作区
git checkout [branch-name]

# 切换到上一个分支
git checkout -

# 建立追踪关系,在现有分支与指定的远程分支之间
git branch --set-upstream [branch] [remote-branch]

# 根据一个特定的提交创建新分支,忘记开新的分支就修改并提交了代码时的处理
git branch test-branch HEAD~1

# 删除分支
git branch -d [branch-name]

# 推送分支到远程仓库
git push origin [branch-name]

# 删除远程分支
$ git push origin --delete [branch-name]
$ git branch -dr [remote/branch]

tag

# 列出所有tag
git tag

# 显示 tag list 和注解
git tag -n

# 在当前commit新建一个轻标签
git tag [tagname]

# 在指定commit新建一个tag
git tag [tagname] [commit]

# 添加注解标签
git tag -a [tagname]

# 添加注解标签并添加注解
git tag -am "message" [tagname]

# 删除本地tag
git tag -d [tagname]

# 删除远程tag
git push origin :refs/tags/[tagName]

# 推送所有tag
git push --tags

# 新建一个分支,指向某个tag
git checkout -b [branch] [tagname]

# 切换到tag
git checkout [tagname]

# tag和分支同名时,显示指定切换到tag
git checkout tags/[tagname]

远程仓库和合并分支

git remote

# 查看远程仓库的 URL
git remote -v

# 添加远程仓库
git remote add origin git@github.com:example/test.git

# 删除远程仓库
git remote rm origin

# 修改远程仓库地址
git remote set-url origin [url]

# 将本地的远端和远端进行同步
git fetch origin

# 将本地的远端合并到本地分支
git merge origin/master

# 拉取远程仓库,这相当于上面两条命令
git pull origin master

# 使用rebase可以使提交的历史记录显得更简洁
git rebase mater

# 也可以指定分支:
git pull origin remote:local

# 推送:
git push origin local:remote

改写提交

# 摘出某个提交
git cherry-pick [hash]

# 交互式提交,当涉及提交修改时使用,如 squash、调整 commit 顺序等
git rebase -i
git rebase -i HEAD~4

# 将 upstream 后的 commit 节点嫁接到 newbase,如果有 branch ,会先 checkout 到这个 branch,再 rebase
git rebase --onto <newbase> <upstream> <branch>

# 删除 topicA~3、topicA~4 这两个 commit
git rebase --onto topicA~5 topicA~3 topicA

# 中途要停止rebase操作
git rebase --abort

# 复原到rebase之前的状态
git reset --hard ORIG_HEAD

1)squash合并多个提交:

在编辑 commit message 时 hash 值前的p(pick)表示 use commit,s(squash)表示 use commit, but meld into privious commit

所以我们可以在 push 到远程仓库之前,把多个 commit 合并成一个。

2)edit使提交成退出状态

除了p、s,常用的还有e(edit)表示 use commit, but stop for amending。保存退出后,修改过的提交呈现退出状态。用 git commit –amend 保存修改,然后 git rebase –continue 。这时,有可能其他提交会发生冲突, 请修改冲突部分后再执行 git add 和 git rebase –continue 。这时不需要提交。

3)merge squash:

# 在 merge 特性分支时,把所有的新提交合并成一个
git merge feature-branch --squash

暂存

# 暂时将未提交的变化移除,稍后再移入
git stash

# 查看所有被隐藏的文件列表
git stash list

# 恢复暂存的文件,不从list中删除
git stash appl

# 从list中删除
git stash drop

# 恢复暂存的文件,并从list中删除
git stash pop

撤销

# 遗弃提交
git reset

# 把当前的 HEAD 重置到前一个,丢弃最新commit
git reset HEAD~1

# 撤销上一次提交,并且变更还保持在 staging area
git reset HEAD~1 --soft

--soft 只取消提交,将上一次的修改放入 staging area,不修改索引和工作树

--mixed 默认模式,复原修改过的索引的状态,将上一次的修改放入 working directory,修改索引,不修改工作树

--hard 彻底取消最近的提交,直接将上一次的修改抛弃,修改索引和工作树

三种都会修改HEAD位置

# 抛弃某一次的修改,使用上次提交的版本
git checkout

# 安全地取消过去发布的提交
git revert
git revert HEAD~2

1)git reset与checkout区别:

git reset 使用仓库中的版本覆盖 staging area 中的,如果 working directory 该文件没有其他修改,则 staging area 中的修改将应用到 working directory 中。反之working directory 中的版本将被保留,丢弃 staging area 中的修改。

git checkout 则是使用 staging area 的中的版本覆盖 working directory。

2)git revert与reset区别:

与 reset 不同的是,revert 只会撤销当前的 commit,而之后的 commit 操作的修改还会保留,但是 reset 还会将之后的所有 commit 操作的修改全部退回 staging area 或丢弃。

3)撤消合并:

假如还没推送到远端,可以reset掉
git reset --hard HEAD~

如果已经推动到远端,可以用revert
git revert -m 1 HEAD

diff

# 显示暂存区和工作区的差异
git diff

# 显示暂存区和上一个commit的差异
git diff --cached [file]

# 显示工作区与当前分支最新commit之间的差异
git diff HEAD

# 显示两次提交之间的差异
git diff [first-branch]...[second-branch]

# 显示今天你写了多少行代码
git diff --shortstat "@{0 day ago}"

log

# 以图形展示
git log –graph

# 可以显示包含标签资料的历史记录
git log --decorate

# 单行显示过去5次提交
git log -5 --pretty --oneline

# 显示第一个父commit节点,而不显示merge的commit节点,这样会有一个更清晰的视图
git log –first-parent

# 显示全部分支
git log –all

# 更清晰地显示
git log --graph --decorate --pretty=oneline --abbrev-commit --all

git log --color --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit

其他命令

# 查看某个文件的修改人
git blame

# 优化git仓库,git repack 将版本库未打包的松散对象打包
git repack -d

# 条件搜索及正则表达式搜索
git grep
git grep "TODO"

# 二分法查找快速定位到bug位置
git bisect
git bisect HEAD origin
git bisect run make test
git bisect reset

# 可以列出所有的操作记录,通过reflog找到 commit 的hash,然后 cherry-pick 找回
git reflog

# 获取命令的帮助信息
git help [命令]
git [命令] --help

# 获取当前的状态,git会提示接下来的能做的操作
git status

# Git 组织大型项目的一种方式
git submodule

git内部

Git仓库下有一个.git目录,一般包括下面的内容:

  • config
  • index
  • HEAD
  • hooks/
  • info/
  • logs/
  • objects/
  • refs/

1)config

仓库的配置文件

2)index

索引,index文件保存暂存区信息

3)HEAD

HEAD文件指示目前被检出的分支

4)objects

你提交到一个Git代码仓库中的所有文件,包括每个提交的说明信息(the commit info)都在目录 .git/objects/中存储为实体。

一个实体以一个40字符长度的字符串(该实体内容的SHA1哈希值)来标识。

实体有4类:

  • blob – 存储文件内容
  • tree – 存储目录结构和文件名
  • commit – 存储提交的说明,组成Git的提交图谱
  • tag – 存储带注解的标签(tag)

5)refs

Git中,一个分支(branch)、远程分支(remote branch)或一个标签(tag)(也称为轻量标签)仅是指向一个实体的一个指针,这里的实体通常是一个commit实体。

这些引用以文本文件的形式存储在目录.git/refs/中。

  • refs/heads/xxx 本地分支
  • refs/remotes/origin/xxx 远端分支
  • refs/tags/xxx 本地tag

git提交规范

feat: 添加了xx功能

xx功能描述

阮一峰Commit message 和 Change log 编写指南

三种工作流程

1)Git flow:项目存在两个长期分支,主分支 master 和开发分支 develop。这个模式是基于”版本发布”的,而补是”持续发布”

2)Github flow:只有一个长期分支,就是 master,”持续发布”

3)Gitlab flow:Gitlab flow 的最大原则叫做”上游优先”(upsteam first),即只存在一个主分支 master,它是所有其他分支的”上游”。只有上游分支采纳的代码变化,才能应用到其他分支。

阮一峰Git 工作流程

命令行

常用命令行

pwd        显示当前工作目录          process working directory
cd         切换目录                 change directory
mkdir      创建目录                 make directory
mkdir -p   递归创建多个目录          --parents no error if existing, make parent directories as needed
ls         列出目录内容             list
ls -a      可以显示.开头的文件       all
ls -l      列出文件的详细信息        long listing format
touch      创建文件                
rm/rmdir   删除文件/目录             remove
rm -r      删除目录                  --recursively
mv         文件或目录的移动或更名     move
cp         将文件拷贝至另一文件       copy
echo       输出到文件                  like echo 1 > test.txt
cat        显示文件内容和合并多个文件   like cat test.txt,also like cat file1 file2 > file
less       按页显示文件                  
clear      清屏(ctrl + l)
history    查看最近用过的命令
du         统计目录/文件所占磁盘空间的大小    disk usage                                    
du -sh     以易读的方式显示总共大小           --summarize --human-readable
ps         报告程序状况                      process status
head       显示开头某个数量的文字区块         like head -n 3 test.txt
tail       显示结尾某个数量的文字区块
ping       网络管理常用的3个命令
ipconfig
netstat
xxx -h     至少可以通过以下三种中的一种获取命令的帮助信息
xxx --help
man    xxx

快捷键

Ctrl + A :光标移动到行首

Ctrl + E :光标移动到行尾

Ctrl + U :删除光标所在位置之前的所有字符(不含当前位置字符)

Ctrl + K :删除光标所在位置之后的所有字符(含当前位置字符)

Ctrl + W :删除光标所在位置之前的一个单词

Ctrl + R :根据输入搜索以往使用过的命令

小技巧

Alt + .     使用上一次命令的最后一个参数
!!          上一次命令
↑       显示上一次命令
.           当前目录
..          上一层目录
~           根目录
-           上一次目录
|           管道(pipe),前一个命令的输出为后一个命令的输入,like cat test.txt | less

多个命令之间可以用;或&&分隔,前者命令错误不中断

vim

简明 VIM 练级攻略

参考

阮一峰 Git

猴子都能懂的Git

Pro Git中文