markdown [Git基本操作]初始版本来自:https://github.com/levinit/itnotes/raw/master/git%E5%9F%BA%E6%9C%AC%E6%93%8

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了markdown [Git基本操作]初始版本来自:https://github.com/levinit/itnotes/raw/master/git%E5%9F%BA%E6%9C%AC%E6%93%8相关的知识,希望对你有一定的参考价值。

Git 是 Linus Torvalds 在 2002 年用 C 语言编写的一个**分布式版本控制系统**。

---

[TOC]

如未说明,尖括号 <> 内的内容表示其并非 git 命令参数,而是用户定义的内容(如具体
仓库名、分支名、文件名等等)。

参考:[git-scm](https://git-scm.com/book/zh/v2)
[git 简明指南](https://rogerdudler.github.io/git-guide/index.zh.html)
[图解 git](https://marklodato.github.io/visual-git-guide/index-zh-cn.html)
[git 参考手册](http://gitref.org/zh/creating/)
[archlinux-wiki:git](https://wiki.archlinux.org/index.php/Git_(%E7%AE%80%E4%BD%93%E4%B8%AD%E6%96%87))
[猴子都能看懂的 git 入门](http://backlogtool.com/git-guide/cn/)

---

# 安装和初始设定

* 安装 git

  Linux:根据发行版不同,使用安装命令安装`git`包。

  Mac OS X :安装 Xcode(含xcode command line tools),自带 git,或 `brew install git`。

  Windows :[Git for Windows](https://git-for-windows.github.io/)

  * 图形化 git 例如:

    * gitk 命令行自带图形界面,在 git 仓库中执行`gitk`或在任何地方执行`git gui`启动。
    * [gitkraken](https://www.gitkraken.com/)
    * [source tree](https://www.sourcetreeapp.com/)
    * [github desktop](https://desktop.github.com/)
    * [git-cola](https://git-cola.github.io/)

- 初始设定

  设置用户名和邮箱,图形界面到其相关设置选项里设置,命令行:

  ```shell
  git config --global user.name "Your Name"
  git config --global user.email "email@example.com"
  ```

  更多设置见后文 --git[配置](#配置)

  从本地仓库向远程仓库推送的基本操作流程:

  在本地仓库内进行操作 - > 在[本地仓库创建快照版本](#提交快照)-> 将本地仓库快
  照[推送到远程仓库](#推送和下载分支)

# 仓库创建和远程关联

## 创建本地仓库

* 创建(/ 初始化)仓库 :`git init`

* 仓库空间划分概念:

  * **工作区**(working directory ):存放当前工作文件

  * **暂存区**(stage):存放通过`git add`添加的文件。

  * **版本库**(repository ):项目的各个版本(快照)。

## 关联远程仓库

将本仓库与其他仓库关联(例如远程服务器上的仓库),以推送本地仓库数据到关联的仓库中。

- 添加关联

  可以克隆远程仓库或者直接添加远程仓库信息以进行关联:
  - 克隆仓库:`git clone <url/repo-name>` 

    几种不同的协议示例:

    ```shell
    git clone https://example.com/path/to/repo-nam.git
    git clone git@example.com:someone/path/to/repo-name.git
    git clone ssh://example.com/path/to/repo-name.git
    git clone git://example.com/path/to/repo-name.git
    ```

    此外还支持 ftp、git 、 rsync 等协议。
    - 克隆远程仓库的某个分支

      ```shell
      git clone <remote_repo> -b <branch>
      ```

      分支相关信息参看[分支管理](#分支管理)

  - 直接添加远程仓库信息

    ```shell
    git remote add [<option>] <host-name> <url>
    ```

    host-name是远程主机名,改名字由用户自定义,如按一般习惯将其命名为`origin` 。

- 删除关联:`git remote remove <repo-name>`

- 查看远程仓库信息:`git remote`

  * 查看远程仓库地址:`git remote -v`

- 远程仓库更名:

  ```shell
  git remote rename <oldname> <newname>
  ```

- 修改远程仓库地址(以origin为例):

  ```shell
  git remote set-url origin <new-url>
  ```

- 添加远程仓库地址(以origin为例):

  ```shell
  git remote add-url --add origin <another-url>
  ```

  也可以修改仓库目录中.git下的config文件的相关信息进行仓库更名和地址修改。config文件部分内容示例(该origin远程仓库对应三个地址):

  ```shell
  [remote "origin"]
  	url = git@github.com:levinit/itnotes.git
  	url = git@git.coding.net:levinit/itnotes.git
  	url = https://github.com/levinit/itnotes.wiki.git
  	fetch = +refs/heads/*:refs/remotes/origin/*
  ```

  提示:向origin推送(push)时将依次推送到三个url地址,但拉取(pull)时仅拉取第一个url地址的仓库内容。

`git remote -h`可获取更多 remote 相关命令帮助。更多远程仓库相关内容参看下
文[推送和获取分支](#推送和获取分支)

# 快照基本操作

Git 保存数据是对文件系统的一组快照。 每次提交更新时,它主要对当时的全部文件制作
一个**快照**。如果文件没有修改,Git 只保留一个链接指向之前存储的文件。一份快照就是备份的一个文件版本,Git 的工作就是创建和保存项目的快照及与之后的快照进行对比。

一个简单的快照生成流程:

工作区文件 --add--> 进入暂存区 --commit--> 加入版本快照

## 仓库状态

* 查看当前仓库状态:`git status`
  * 简略地显示:`git status -s`
* 查看仓库变动内容:`git diff`
  * 显示变动内容摘要:`git diff --stat`
    * 查看已暂存的改动:`git diff --cached`
  * 显示**最近**快照和工作区内容的差异:`git diff HEAD`
    * 显示指定文件的差异`git diff HEAD --<filename>`
* 查看历史提交:`git reflog`

## 提交快照

提交一个快照需要两步操作:

1. 添加文件到暂存区:`git add <file-name>`

2. 提交快照:`git commit`

每次提交都会生成一个哈希码,即是 commit id。修改过的文件如果不添加到暂存区,就不
会加入到快照中。

---

* 将**所有变动**添加到暂存区:`git add -A`

  变动包括(对文件的)新建、修改和删除,A 是 --all 的缩写,相当于以下两条命令:

  * `git add .` 将所有**新建和修改(但不包括删除)**提交到暂存区
  * `git add -u` 将所有**修改和删除(但不包括新建)**提交到暂存区(u--update ,
    只标记本地有改动的已追踪文件)
  * **撤销暂存区**修改:`get reset HEAD <file-name>`

- 提交快照并添加注解:`git commit -m "about"` about 是注解内容

  `-m "about"`还可和其他操作(如 merge 和 tag 等)合用。

- 将**工作区变动直接添加到快照**并增加注解:`git commit -am "about"`

- 将**暂存区**的变动**追加**到上一份快照:`git commit --amend`

  在提交一个快照后又变动了部分内容,但是想把新的变动追加到这个快照中时使用。

  1. 将这些变动添加到暂存区 (git add)

  2. 执行`git commit --amend` 追加

     该命令会**生成的新的 commit id 并替换掉原 commit id**; 如果暂存区没有内容
     , 可以利用该命令修改上一次提交的注解。

## 回退快照

- 回退文件版本

  使用该文件在版本库里的版本替换工作区中的版本,需要**先撤销暂存区修改,再撤销工作区修改**:

  1. **撤销暂存区**修改:`get reset HEAD <file-name>`
  2. **撤销工作区**修改:`git checkout -- <file-name>`

- 删除快照中的文件

  1. git rm <file-name>`
  - `git commit`

  移动或改名版本库中的文件`git mv <file-name> <new-file-name>`同理,需要进行`git commit`快照提交才能生效。

  默认情况下`git rm <file-name>`也会将文件从暂存区和硬盘中(工作目录)删除。如果
  要在工作目录中留存该文件,可以使用`git rm --cached <file-name>`保留。

- 版本回退——回退到某个指定的版本

  * `git reset --hard <commit-id>`   回到指定版本并抛弃该版本之后的所有提交
  * `git revert --hard <commit-id>`  回到指定版本并提交一次

  commit id 可以使用前文的`git reflog`命令在历史操作记录中查找。

  回退之后要推送到远程仓库使用`git push origin HEAD --force`

  * 回退到上一个版本:`git reset --hard HEAD^`

    关于`HEAD`、`^`和`~`

    * `HEAD`表示**当前分支的当前版本**;

    * `^`( caret)表示父提交,当一个提交有多个父提交时,可以通过在`^`后面跟一
      个**数字**,该数字表示第几个父提交,`HEAD^`相当于`HEAD^1`(第一个父提交)
      ;

      上一个版本就是`HEAD^`或`HEAD^`,上两个版本就是`HEAD^^`。

    * `~`(tilde )后跟一个数字 n 相当于**前面连续的**n 个`^`,`HEAD ~ 2`就相
      当于`HEAD^^`或`HEA^1^1` 。

## 快照信息

```shell
git rev-list --count HEAD #最近一次提交快照的版本号(即第几次快照)
git rev-parse HEAD #最近一次提交快照的hash值
git rev-parse --short HEAD #最近一次提交快照的前面部分(7位)hash值
```

# 分支管理

分支管理经验示例:

* master 分支 -- 用于稳定更新,同步到远程仓库;
* dev 分支 -- 用于开发,同步到远程仓库;
* bug 分支 -- 用于修复问题,不必同步 ;
* feature 分支 -- 用于添加新特性,根据情况同步;

……

## 分支查看

* 列出所有分支:`git branch`

  ```shell
  #查看包含指定版本的分支
  git branch --contains <commmit-id>
  #查看本地分支与远程分支对应关系
  git branch -vv
  ```

* 列出**当前**分支历史记录:`git log`

  * 查看指定的分支:`git log <branch-name>`
  * 显示拓扑图:`git log -- graph`
  * 简洁模式查看:`git log --oneline`
  * 显示所有的提交信息:`git --decorate`
  * 特定过滤:

    * 查找有特定内容的注释的分支:`git log --grep=<content>`

    * 查找特定作者提交的分支:`git log --author="name"`( name 是作者名字)

    * 按时间范围查看分支:`git log --since/befor/until/after={time-discription}`
      示例:`git log --oneline --before={3.weeks.ago} --after={2016-06-06} --no-merges`

      `--no-merges`作用是隐藏合并提交的分支,`--oneline`是每个提交显示一行

## 创建、切换、合并和删除分支

* 创建和切换

  * 创建并切换分支:`git checkout -b <branch-name>` 也可以先创建分支再切换分支

    * 创建分支:`git branch <branch-name>`
      * 创建一个空分支:`git checkout --orphan <branch-name>`
    * 切换分支:`git checkout <branch-name>`

  * 创建并切换分支,同时关联远程分支:`git checkout -b <branch-name> origin/<branch-name>`

  * 重命名分支:`git branch -m <old-branch-name> <new-branch-name>`

    这只是将本地分支重命名,如果要将远程分支也重命名,只需要将本地重命名后的分支推送给原来已经关联的远程分支即可,参看[# 推送和下载分支](推送和下载分支)有关推送的说明。

- 合并

  合并是将指定分支合并到**到当前分支**:`git merge <branch-name>`

  如果合并分支时存在冲突则需要先解决冲突。

  合并分支时可在命令后面加上`-m "info"`来添加一个合并说明。

  * 普通方式合并分支:`git merge --no-off <branch-name>`

    通常合并分支时,如果可能,Git 会用 Fast forward 模式,但这种模式下,删除分支
    后,会丢掉分支信息。加`--no-off`参数,可以用普通模式合并。

  * 合并指定分支到当前分支并**丢弃当前分支的历史快照**:`git rebase <branch-name>`

    将指定分支(branch-name )合并到**当前分支**,**合并后的版本**将 “ 嫁接 ” 到
    该指定分支上并取代该分支。而**当前分支的其余历史快照将会被丢弃**,这些历史快
    照将会**临时**保存为补丁 (patch,补丁在`.git/rebase`目录中 )。

  ​

- 删除分支:`git branch -d <branch-name>` 强行删除**未被合并过**的分支:`git branch -D <branch-name>`

  这只是删除了本地的分支,如果要删除远程仓库的分支,参看下文。

## 推送和获取分支

* 分支追踪:设置远程某分支与本地某分支的关联(远程某分支和本地某分支建立起一一对应的关系)
  * `git branch --track <branch-name> <origin/branch-name>`
  * `git branch --set-upstream-to=origin/<branch-name> master`

- 推送分支:`git push <repo-name> <local-branch-name>:<remote-branch-name>`

  * 如果省略远程分支名,则表示远程分支名和本地当前分支名一致,如此远程分支名不存在,则会在远程仓库新建该分支。

    示例:`git push origin master`

  * 如果省略本地分支名,则表示删除指定的远程分支,因为这等同于推送一个空的本地分支到远程分支。

    示例:`git push origin :dev`

  * 如果本地分支名和远程分支名都省略,则表示将当前分支推送到追踪的远程分支。

    示例:`git push origin`

  push 命令最后加上`--tags`会推送未曾推送过的标签,参看[标签管理](#标签管理)。

  * 只推送当前分支:`git push`(如果当前分支**只有一个追踪分支**时可以使用)
  * 推送全部分支:`git push -all origin`
  * 推送并指定默认远程跟踪分支:`git push -u <repo-name> <branch-name>`
  * 强制推送:`git push --force origin` (使用本地快照版本强制覆盖到远程仓库)

- 获取分支

  * 获取当前分支新内容:`git fetch <repo-name>` 从远程仓库下载新内容
  * 拉取并合并到当前分支:`git pull <repo-name>` 从远程仓库下载新内容并尝试合并
    到本地当前分支(相当于先 fetch 获取新内容,然后 merge)

## 工作区存储

可**暂存当前工作区**以操作新分支。

* 存储工作区:`git stash`
* 列出存储的工作区:`git stash list`
* 恢复存储的工作区

  * 恢复工作区且**保留**工作区内容:`git stash apply`

    * 恢复指定指定编号的工作区:`git stash apply stash@{number}`( number 是一个
      数字)

      编号可用`git stash list`命令查看。

  * 恢复工作区并**删除**工作区内容:`git stash pop`

* 删除工作区:`git stash drop`

# 标签管理

提交快照时的 commit id 是一串数字 + 字母(hash code ),难以记忆,使用相对不变
,tag 可以对提交打上容易记住的标签。

* 查看标签:

  * 列出所有标签:`git tag`
  * 查看指定标签信息:`git show <tag-name>`

* 添加标签

  可以在打标签命令后添加 `-m "about"`(about 是标签注解 ) 给标签添加注解。

  * 给当前分支打标签:`git tag <tag-name>`
  * 给指定快照打标签:`git tag <tag-name> <commit-id>`
  * 使用 GPG 签名打标签:`git tag -s <tag-name>`

* 推送标签

  创建的标签都只存储在本地,**不会自动推送**到远程仓库。

  * 推送一个本地标签:`git push <repository-name> <tag-name>`
  * 推送全部未推送过的本地标签:`git push <repository-name> --tags`

* 删除标签

  * 删除一个本地标签:`git tag -d <tag-name>`
  * 删除一个远程标签:`git push <repository-name> :refs/tags/<tag-name>`

# git 配置

## 忽略规则

创建 .gitignore 文件,添加特定匹配规则就可以禁止相应的文件推送到远程仓库。
[github 提供的 .gitingore 文件](https://github.com/github/gitignore)

windows 下:在资源管理器里新建一个 .gitignore 文件,系统会提示必须输入文件名,可
在文本编辑器里 “ 保存 ” 或者 “ 另存为 ” 就可以把文件保存为 .gitignore 了。

* 校验 .gitingore 文件:`git check-ignore`
* 校验指定规则:`git check-ignore -v <rule>`
* 强制添加被忽略的文件:`git add -f <file-name>`
* .gitingore 编写:
  * `#`注释
  * 一行一条
  * 同名匹配
  * 可使用通配符

## 配置

git 的配置文件在`~/.gitconfig`,仓库的配置文件是仓库内的`.git/config`。

可运行`git help` `git config`和`man git`查看更多帮助信息。

官方文
档[git-config Manual Page](https://www.kernel.org/pub/software/scm/git/docs/git-config.html)e

部分设置命令:

加上`--global`参数,则设置内容对当前用户生效,不加`--global`则对当前仓库生效。

* 检查配置情况:`git config --list`

* 设置默认编辑器,如 nano: `git config --global core.editor nano`

* 设置默认对比工具,如 meld:`git config --global merge.tool meld`

* 彩色输出:`git config --global color.ui true`

* 中文文件名显示:`git config --global core.quotepath false`(避免中文显示成数字
  )

* 显示历史记录时每个提交的信息显示一行: `git --global config format.pretty oneline`

* 设置用户名和电子邮箱

  ```shell
  git config --global user.name "your name"
  git config --global user.email "email@example.com
  ```

* 协议更换

  如 https 替代 git 协议

  ```shell
  git config --global url."https://".insteadof "git://"
  git config --global url."https://github.com/".insteadof "git@github.com:"
  ```

* 设置代理

  如使用 socks5,本地 ip 和端口是 127.0.0.1:1080

  ```shell
  git config --global http.proxy socks5://127.0.0.1:1080
  git config --global https.proxy socks5://127.0.0.1:1080
  #取消设置的代理
  git config --global --unset http.proxy
  git config --global --unset https.proxy
  ```

* 设置命令别名:`git config --global alias.<another name> status`

      git config --global alias.ci commit
      git config --global alias.br branch
      git config --global alias.unstage 'reset HEAD'
      git config --global alias.graph 'log --graph --oneline --decorate'

  # git 服务简易搭建

1. 安装 git、openssh ,开启 ssh 服务:`systemctl start sshd && systemctl enable sshd`

2. 创建运行 git 服务的用户(可选)

3. 初始化 Git 仓库:`git init --bare <name.git>`(服务器上的 Git 仓库通常都以
   .git 结尾)

   如果要从已经存在的仓库克隆一份作为新的裸仓库:`git clone --bare <repo-name> <new-repo-name>.git` (注意:此命令会**只复制**出原仓库中的`.git`目录)

   也可以将原仓库的`.git`目录复制并改名成一个新仓库:`cp <repo-name>/.git <new-repo-name>.git`

   如果服务器的 ssh 服务更改了默认使用端口,参照前文 “ 远程关联 - 从远程仓库克隆
   ” 中的使用方法。

4) 安全管理

* 非对称加密

  在客户机使用`ssh-keygen`生成非对称加密的公私钥,在服务器上运行 git 的用户
  的`~/.ssh/authorized_kesys`文件中,添加有客户机公钥。(注意:保证`.ssh`文件夹
  权限为 700 以及`authorized_kesys`文件权限为 600,公钥一行一个。)

* git 文件夹权限

  git 仓库文件夹的权限设置为 755(即`rwxr-xr-x` ),不允许其他用户更改(仅通过添
  加 SSH 公钥来添加允许更改的客户端,这些被允许的客户端是通过执行 git 服务的用户
  来获取写入权限的)。

* ssh 权限

  ssh 配置文件位于`/etc/ssh/sshd_config` ,如更改默认端口,使用白名单策略等等。

* shell 权限

  假如 git 服务的执行用户名为`git`,编辑`/etc/passwd`文件,找到`git`所在行,将行
  中`/bin/bash`字样(根据不同 shell,也可能是`bin/zsh`等等) 改为`bin/git-shell`
  。

以上是关于markdown [Git基本操作]初始版本来自:https://github.com/levinit/itnotes/raw/master/git%E5%9F%BA%E6%9C%AC%E6%93%8的主要内容,如果未能解决你的问题,请参考以下文章

markdown Git初始化

Git起步

markdown 来自远程fork repo的Git rebase

Git——初始版本控制工具

markdown git rm。 Elimina todos los ficheros borrados。来自:https://stackoverflow.com/a/5147119/3377046

git学习-来自慕课网