Git

# Git

git

  • 工具
  • 版本控制
  • 分布式-基本不担心版本库的丢失
  • 不用连接中央服务器,随地都可以工作
  • 提交到github就可以保证多人协作

[TOC]

# 一、git的三个区

  • 工作区
  • 暂存区
    • 作为过渡层
    • 避免误操作
    • 保护工作区和版本区
    • 分支处理:等版本确定无误后,合并到主分支
  • 版本区(库)

# 二、git命令

# 2.1 创建

创建命令 含义 其他
git init 创建版本库 初始化一个git仓库
touch <file.name> 创建一个文件

# 2.2 查看

查看命令 含义 其他
git status 查看暂存区和工作区的状态
git reflog 文件名 查看版本号 查看恢复的日志 上面有commit_id
cat <file.name> 显示文本内容
git log 查看提交的日志 只会显示部分,按回车往下查看,按键盘Q推出
git branch 查看分支
git branch --merged 查看合并过的分支
git branch --no-merged 查看没有合并过的分支
git config --list 查看所有配置项
git remote 查看远程仓库的名字
git remote -v 查看仓库fetch和push的地址

# 2.3 配置

配置命令 含义
git config --global user.name "Your Name" 设置贡献者名字
git config --global user.email "email@example.com" 设置贡献者邮箱

# 2.4 提交

提交命令 含义 其他
git add <file.name> 将文件提交到暂存区 git add . 将所有文件提交到暂存区
git commit -m "注释" 提交文件到本地库
git commit '注释'--amend 撤销回上一次提交,然后重新提交
git -a -m '注释' 工作区到缓存区再到版本库
git push origin master 同步到远程仓库的版本库中 从远程获取最新版本并merge到本地

不要用 git push --force,而要用 git push --force-with-lease 代替。在你上次提交之后,只要其他人往该分支提交给代码,git push --force-with-lease 会拒绝覆盖。

远程库的名字就是origin,这是Git默认的叫法,也可以改成别的,但是origin这个名字一看就知道是远程库。

# 2.5 撤销

撤销命令 含义 其他
git reset --hard HEAD^ 回退一个版本 从暂存区撤销回工作区
git reset --hard HEAD~<num> 回退n个版本 版本恢复到过去的前n个版本
git reset --hard commit_id 到所指定的版本号的版本 复制commit的id号时只复制前一部分即可
git checkout <file.name> 还原文件 将工作区的版本撤销回版本库的状态
git checkout commit_id <file.name> 指定文件的恢复
git reset <file.name> 撤销某个文件暂存区的提交

git pull后想回退版本

git reflog master (查看本地master分支历史变动记录)
得到一下结果:
    a1ed85e (master) master@{0}: commit: test
    a7575f0 master@{1}: commit: add CHAME
    9dafea8 master@{2}: commit: change
    144aed6 master@{3}: commit (initial): first commit
git reset --hard <COMMIT_ID> (恢复到指定版本)
    git reset --hard master@{0}
1
2
3
4
5
6
7
8

# 2.6 删除

删除命令 含义 其他
git rm <file.name> 只有工作区删了而暂存区没删的时候可以用,用来删除缓存区文件
–git rm -f <file.name> 强制删除工作区和暂存区的文件 f就是force
git rm --cached <file.name> 去掉某个文件的版本追踪 只会删除暂存区的文件,不会删工作区的

# 2.7 分支

分支命令 含义 其他
git branch 分支名 创建分支
git checkout 分支名 切换分支
git merge 分支名 合并分支 先切换到主干,版本改变,master指针往前移
git checkout -b 分支名 创建并切换到新建的分支
git branch -d 分支名 删除分支 只有合并过的分支才能删除
git branch -D 分支名 强制删除没有合并过的分支

# 2.8 命令

对比命令 含义
git diff 工作区和暂存区的对比
git diff --cached 暂存区和版本库的对比
git diff --staged 暂存区和版本库的对比
git diff master 工作区和版本库的对比

# 三、SSH keys

ssh是一种安全的传输模式,github要求推送代码的用户是合法的,所以每次推送时候都要输入账号密码,用以验证你是否为合法用户。

# 3.1 创建

  • 省去每次都要输入密码的步骤
    • 在你的电脑生成了一个唯一的ssh公钥和私钥,公钥放到github上面,私钥放在本机且无法截获。
    • 当你推送的时候,git就会匹配你的私钥是否跟github上面的公钥是配对的,正确就认为你是合法的,允许推送。

# 3.1.1 给git加ssh-key

  1. 查看根目录下是否有.ssh目录

  2. 若没有则生成一个ssh-key ssh-keygen -t rsa -C "email@mail.com" 连按三次回车

  3. 将.~/ssh/id_rsa.pub内容加入你的github中

  4. 设置你的git用户名及邮箱

git config --global user.name "name"
git config --global user.email "email@mail.com"
1
2
  1. 测试你的ssh-key ssh -T git@github.com 输入yes后若显示 Hi xxx! You’ve successfully authenticated, but GitHub does not provide shell access. 则代表成功。

# 3.1.2 解决github上传ssh-key后仍须输入密码的问题

  • 这种事情通常发生在更换机器后克隆自己仓库的时候,通常我们会使用https方式克隆

    git clone https://github.com/Name/project.git

    这样便会在你git push时候要求输入用户名和密码

  • 解决的方法是使用ssh方式克隆仓库 git clone git@github.com:Name/project.git

  • https方式克隆后改ssh方式

    只需将 .git/config文件中的 url = <https://github.com/Name/project.git> 一行改为 url = git@github.com:Name/project.git

# 四、一般操作

远程要先建仓库。

  1. 初始化一个Git仓库git init

  2. 添加文件到Git仓库

    1. git add <file.name>可反复多次使用,添加多个文件
    2. git commit
  3. 随时掌握工作区的状

    git status
    
    1
    1. 若修改过,查看修改内容git diff
  4. 在版本的历史之间穿梭

    1. HEAD指向的版本就是当前版本git reset --hard commit_id
    2. git log查看提交历史,确定回退版本
    3. git reflog查看命令历史,确定重返版本
  5. 关联一个远程库

    git remote add origin git@server-name:path/repo-name.git
    
    1
    • 示例:$ git remote add origin git@github.com:michaelliao/learngit.git
  6. 第一次推送master分支的所有内容

    git push -u origin master
    
    1
    • 由于远程库是空的,我们第一次推送master分支时,加上了-u参数
    • Git不但会把本地的master分支内容推送的远程新的master分支,还会把本地的master分支和远程的master分支关联起来
    • 在以后的推送或者拉取时就可以简化命令。
  7. 以后的每次本地提交后,git push origin master推送最新修改

  8. 创建新的分支,提交后合并分支

    $ git checkout -b branchName
    $ git add .
    $ git commit -m 'XXX'
    $ git push origin branchName
    $ git checkout master
    $ git merge origin/branchName
    $ git push
    
    1
    2
    3
    4
    5
    6
    7

# 五、多人协作解决冲突

git fetch相当于是从远程获取最新版本到本地,不会自动合并

  • git diff master origin/master
  • git merge orgin/master

# 5.1 开源项目协作

  • fork
  • pull request

# 六、报错案例

# 6.1 案例一

git push -u origin master
1
  • 报错如下:
error: failed to push some refs to 'git@github.com:你的远程库名.git'
hint: Updates were rejected because the tip of your current branch is behind
hint: its remote counterpart. Integrate the remote changes (e.g.
hint: 'git pull ...') before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.
1
2
3
4
5
  1. 由于两者不同步,因此需要先pull,进行合并然后在进行push。
    • 将远程文件同步下来git pull --rebase origin master
    • 执行推送git push -u origin master

# 6.2 案例二

remote add origin git@github.com:djqiang(github帐号名)/gitdemo(项目名).git
1
  • 报错信息:fatal: Could not read from remote repository
  • 原因:remote origin already exists.
  • 解决办法如下:
$ git remote rm origin
$ git remote add origin git@github.com:djqiang/gitdemo.git
1
2

# 七、Git钩子

参考教程:Git 钩子 hook 介绍与使用 (opens new window)

# 7.1 启用及触发

# 7.1.1 启用

  • .git/hooks下的文件名,去掉后缀.sample即可启用。

# 7.1.2 触发

# 7.1.2.1 post-receive
  • 在整个过程完结以后运行,可以用来更新其他系统服务或者通知用户。
  • 即,当服务端收到一个push操作请求时触发,可用于检测push的内容。
# 7.1.2.2 update
  • 与pre-receive相似,但当一次push想更新多个分支时,pre-receive只执行一次,而此钩子会为每一分支都执行一次。

# 八、其他

npm --registry https://registry.npm.taobao.org
1

# 8.1 替换远程仓库关联

  1. 解除旧分支的关联
git remote remove origin
1
  1. 关联新分支
git remote add origin https://xxxxxxx/wangdong/helloworld.git
1

# 8.2 强制覆盖本地代码

git fetch --all &&  git reset --hard origin/master && git pull
1

第一个是:拉取所有更新,不同步; 第二个是:本地代码同步线上最新版本(会覆盖本地所有与远程仓库上同名的文件); 第三个是:再更新一次(其实也可以不用,第二步命令做过了其实)

备注: 命令连接符 && 的意思是 前一条命令执行成功才执行后一条命令。 扩展:命令连接符 ;; 的意思是 不论前一条是否执行成功都继续执行后一条命令。

# 8.3 禁止上传指定文件

# 8.3.1 规则

# 此为注释 – 将被 Git 忽略

*.a # 忽略所有 .a 结尾的文件

!lib.a # 但 lib.a 除外

/TODO # 仅仅忽略项目根目录下的 TODO 文件,不包括 subdir/TODO

build/ # 忽略 build/ 目录下的所有文件

doc/*.txt # 会忽略 doc/notes.txt 但不包括 doc/server/arch.txt
1
2
3
4
5
6
7
8
9
10
11

# 8.3.2 已经推送(push)过的文件,想在以后的提交时忽略此文件,即使本地已经修改过,而且不删除git远程库中相应文件

  • 忽略文件
git update-index --assume-unchanged Xml/config.xml
1
  • 忽略目录
git update-index --assume-unchanged $(git ls-files | tr '\n' ' ')
1

# 8.3.3 已经推送(push)过的文件,想从git远程库中删除,并在以后的提交中忽略,但是却还想在本地保留这个文件

git rm --cached Xml/config.xml
1

# 8.4 修改分支名

  • 对于未提交到远程的,直接git branch -m oldName newName

  • 而已经提交到远程的,其实就是删除远程的,再把本地的新分支推到远程去

    • 删除远程分支
    git push --delete origin oldName
    
    1
    • 上传新命名的本地分支
    git push origin newName
    
    1
    • 本地分支和远程分支关联
    git branch --set-upstream-to origin/newName
    
    1