1

本文是本人在学习和使用 Git 过程中的一些记录。以备查阅。
随时更新。本文地址:https://segmentfault.com/a/1190000008367711

另外推荐我的另一个 Git 文章:实际操作 Svn 迁移到 Git

Reference

git使用详细介绍
使用 Git 管理源代码
实际操作 Svn 迁移到 Git
git rebase简介(基本篇)
git merge和rebase的区别
git 撤销commit
Git修改已经提交的注释或日志
为 Git 配置扩展命令
git 本地分支和远程分支的跟踪信息的对应
Git push与pull的默认行为
Git基本使用
Permission denied(publickey)错误
为 git 实现 'svn info' 的功能
设置ssh key后push为什么还要输入用户名和密码

Git 基本概念

仓库:也就是 .git 文件。Git 建基于该文件的索引来跟踪改变。每次 commit 都会刷新一次仓库。

Git 忽略机制:可以在与 .git 文件同级的目录下,创建一个 .gitignore 文件,在文件中写上忽略的对象。可以用通配符,也可以用 “#” 注释掉。

项目:一个 repository 对应一个项目;一个 repo 往往又多个仓库。在 GitLab 上面的对应关系是:Group --> Project.

Git 命令

与 svn 类似的命令

git commit在本地更新当前的变更。一般都会加上 -m 或者 -F 参数来附上 message。每次 commit 之后,就会生成其对应的 SHA-1 格式的 commit ID,类似于 svn 里面的 svn version。
git help xxx:查看相应 git 命令的帮助信息
git diff .:查看当前目录的修改内容
git add xxx:将文件 / 目录下的全部内容纳入版本控制
git rm xxx:将文件 / 目录下的全部内容剔除出版本控制并删除
git log:查看当前 repo 的 log 历史。可以带上 -x(x为自然数)指定只显示最近几个 log
git mv xxx:移动 / 重命名文件 / 目录
git status:与 svn stat 类似,只是输出格式不同。修改的文件会在当前列表前面列出,开头是 “# modified: ...”

Git 特有的新命令

  • git init:在当前目录创建一个新的 .git 仓库

  • git merge:合并指定分支——这是一个庞大的课题,也是 git 的精髓,这里还真没法一时半会说清楚

  • git checkout:切换到本地分支,具体如下:

    • 创建一个新的本地分支:git checkout -b xxx

    • 切换到指定的本地分支:git checkout xxx

    • 切换到服务器上的某分支:git checkout xxx——这个命令会在本地临时创建一个分支

    • 查看服务器上的分支列表:git branch -r

    • 查看分支的基准关系:git branch -vv

    • 切换到某个 commit ID:git checkout 相应的commit_id号码

    • 切换到某个 tag:git checkout xxx

    • 基于某个分支(本地 or 服务器),在本地创建一个新的分支:git checkout -b 新分支名 基准分支名

    • 还原指定文件至修改之前的状态:git checkout 文件/目录名

  • git branch:分支管理。其中部分命令在上面 git commit 也有提及。下面也列出主要的功能:

    • 查看本地的所有分支:git branch

    • 查看服务器上的分支列表:git branch -r

    • 查看分支的基准关系:git branch -vv

    • 查看当前分支的信息:cat .git/HEAD

    • 删除本地分支:git branch -D xxx

    • 比较指定的分支差异:git diff 分支A 分支B

  • git tag:基于某个分支 / commit ID 创建一个 tag:git tag tag名称 基准名称

  • git clone:从服务器中初始化一个仓库,但需要自行添加 .gitignore 文件。

    • 比如:$ git clone https://github.com/Andrew-M-C/SMB-CIFS_discovery.git .

  • git pull:更新服务器代码到本地仓库中,类似于 svn up

  • git push:将本地修改上传至服务器。这个功能也略微复杂,下文再说

  • git fetch:类似于 pull,但是不会自动 merge。

Git push

这个命令实际上可以用来控制远程服务器上的分支。比如:

  • 将本地分支的内容推送到服务器的指定分支上:git push origin 本地分支名:远程分支名

  • 基于本地分支,在远程服务器上新建一个分支:git push origin 本地分支名:新的远程分支名

  • 删除远程服务器上的分支:git push origin :远程分支名,注意 “origin” 和冒号之间有空格

SSH key

Git 可以用 HTTPS 和 SSH 两种方式与 Git 服务器交互。如果仅仅是获取一个只读的 Git 仓库的话(比如从 GitHub 上面拉取别人的开源工程),用 HTTPS 就够了。如果是自己的工程,推荐使用 SSH 方式。

首先,你要配置好你本地的账户名和邮箱名:

git config --global user.name "你的账户"
git config --global user.email "邮箱"

使用 SSH 需要在服务器上上传自己的公钥。生成方法:

ssh-keygen -t rsa -C "你的账户 / 邮箱名"

SSH key 放在 ~/.ssh/id_rsa.pub 文件中

切换账户

本地快速切换账户的时候(同一台机器上操作不同的服务器上的工程),我没有什么方便的方法,也只有使用git config ... 和上一小节提及的 ssh 命令来切换,不过 ssh-keygen 就不用了,改为复制相应的文件就行了。

但如果只是执行上面的几个操作的话,会出现 “Agent admitted failure to sign using the key.” 的错误。如果是这样的话,那么请执行一次 ssh-add,然后再去操作就可以了

Git rebase 的用法和与 merge 的区别

Git rebase 是啥

用来把一个远程分支合并到本地分支。简单语法:git rebase 远程分支 本地分支
其中本地分支可以不指定,默认是当前分支。

比如有一个 git 仓库的分支情况为:

             A---B---C topic
            /
       D---E---F---G master

此时如果在 topic 分支上执行 git rebase master,则分支表会变成:

                     A'--B'--C' topic
                    /
       D---E---F---G master

换句话说,git rebase 就是:
  将当前分支的修改先 patch 下来,然后回退至原版。更新远程分支的修改之后,再应用 patch。

与 git merge 的区别

差别就是 git merge 不会去做 patch 动作。同样以上图为例,在 topic 分支执行了 git merge master 之后,分支情况变成:

             A---B---C topic
            /         \
       D---E---F---G---H master

与 git pull 的区别

实际上,git pull 就是分别调用 merge 和 rebase

  • 使用 merge 模式:git pull

  • 使用 rebase 模式:git pull --rebase

Git commit 修改

对于上一个尚未上传到服务器上的 git commit,可以重写 log 或者是直接撤销。

  • 修改 commit log:git commit --amend 进入界面修改

  • 删除指定 commit ID 的修改:git reset --hard commit_id

  • 撤销指定的 commit 但保留修改:git reset --soft commit_id

配置自定义的 Git 命令

详细的原理请参考这篇文章。我喜欢在安装了 Git 之后,配置以下命令:

$ git config --global alias.co checkout
$ git config --global alias.br branch
$ git config --global alias.st status
$ 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"

重建远程 / 本地分支的对应关系

假设本地分支 BrA 对应着远程分支 origin/dev_A。当你基于 BrA 拉出一个新的本地分支 BrB 的时候,远程分支对应关系就没了。这个时候就需要重建远程 / 本地分支的对应关系:

git branch --set-upstream BrB origin/dev_A

将 Git 仓库内容清理干净

这个包含两个事情:

  1. 删除所有不在版本控制之下的文件

  2. 将已修改的文件恢复到版本控制之下的状态

我自己常用的方法并不优雅,但能用。
主要是使用到了rm 命令不会主动删除隐藏文件这一点(因而就不会去删除.git文件夹):

    $ rm * -rf; git co .

但是比较标准的做法其实是这样的:

    $ git clean -fd
    $ git co ./

第一句中的 clean,有三个主要参数:

  • n:显示出要删除哪些目标,但不删除——每次清除之前建议执行一次 git clean -nfd 确认一下

  • f:删除不受版本控制的文件

  • d:删除不受版本控制的目录

GitHub 出现错误提示:“Username for 'https://github.com':”

参见这个问答

因为你用的是 https 而不是 ssh。
你可以更新一下 origin:

git remote remove origin
git remote add origin git@github.com:Username/Your_Repo_Name.git

amc
927 声望228 粉丝

电子和互联网深耕多年,拥有丰富的嵌入式和服务器开发经验。现负责腾讯心悦俱乐部后台开发