指令一览

作用 指令 注释
初始化 git init 生成.git
添加 git add 添加到库
确认添加 git commit -m 后跟””添加备注
查看库状态 git status 包含未commit的内容
查看差异 git diff xxx 对比文件add后的差异
查看版本日志 git log 简化参数--pretty=oneline
查看操作日志 git reflog
回溯git库 git reset 后跟版本号前几位即可
回溯工作区 git checkout -- file 删除工作区内容回退到git库版本 增加-b参数可添加并切换(branch)
删除暂存区文件 git rm 不会删除工作区内容
链接远程库 git remote add 例如git@github.com:xxx2/xxx3.git
连接远程库 git push (-u) 参数<远程主机名> <本地分支名>:<远程分支名>
合并分支 git merge --no-f 禁用fast forward模式
切换分支 git switch
储存便签 git stash git stash pop取回本地,list查看列表
复制改动 git cherry-pick 重复一次commit的改动
查看分支 git branch -r查看远程 -a查看全部 -d删除本地 -D强制删除
查看远程库信息 git remote -v查看详细信息
合并历史提交分叉 git rebase
创建标签 git tag -a名字 -m备注 -push远程仓库:标签名
查询.gitignore文件 git check-ignore

创建版本库

  • 创建目录

    $ mkdir xxx
    $ cd xxx
    $ pwd
    /Users/xxxxxxx/xxx

    pwd命令用于显示当前目录。

  • 通过git init命令把这个目录变成Git可以管理的仓库

    git init
    Initialized empty Git repository in /xxx/xxx/

    目录下通过.git来追踪和管理库。

  • 将文件添加到仓库
    正如将大象放进冰箱需要三部,放如git仓库只需要两部,因为在验证ssh时就打开冰箱门了。

    $ git add xxx
    $ git commit -m “notes”

    解释一下git commit命令,-m后面输入的是本次提交的说明,可以输入任意内容,当然最好是有意义的,这样你就能从历史记录里方便地找到改动记录。
    git commit命令执行成功后会告诉你,n file changed:n个文件被改动(添加的XXX文件)等。

.git库管理

首先用git status查看仓库的当前状态,其中包含了add但没有commit的内容。
如果不记得具体修改了什么内容,使用git diff xxxx来查看对比文件commit前版本的差异。
如果没有文件被修改或者添加,则在git status后:

$ git status
On branch master
nothing to commit, working tree clean

Git告诉我们当前没有需要提交的修改,而且,工作目录是干净(working tree clean)的。

  • 版本的回退
    在对文件进行了多次修改后,可以使用git log来查看不同的版本情况,git log命令显示从最近到最远的提交日志,commit id采用的是SHA1计算得出的数字,用十六进制表示。
    如果嫌输出信息太多,看得眼花缭乱的,加上--pretty=oneline参数,每提交一个新版本,实际上Git就会把它们自动串成一条时间线。
    首先,Git必须知道当前版本是哪个版本,在Git中,用HEAD表示当前版本,每网上一个版本就在HEAD后面加一个^,例如前两个版本HEAD^^
    如果这时候你像回退到之前的版本则使用:

    $ git reset --hard head^

    这个时候版本已经被回退到了head^版本了,且在git log里面以及无法找到回退前的版本了。但是如果没有关闭过命令行窗口,那么有机会找到之前的版本号的,然后使用reset 版本号来回退,且版本号只需要填写前几位以区分即可。你回退到了某个版本,关掉了电脑,想恢复到新版本怎么办?Git提供了一个命令git reflog用来记录你的每一次命令,可以从中找到版本号。

  • git库的工作流程
    首先,在你电脑里面所能见到的文件夹,可以称之为一个工作区(Working Directory),并且.git文件夹并不属于工作区,是git的版本库。而版本库(Repository)包含:称为stage(或者叫index)的暂存区;还有Git为我们自动创建的第一个分支master以及指向master的一个指针叫HEAD。在工作区的时候,我们把文件修改完并git add之后,可以理解为将工作区的东西复制到了版本库的暂存区。而git commit则是将暂存区的东西搬空放进master分支里面,就好比论文定稿一样,而head正是指向当前版本的“论文-最新版”。

  • 版本库的回退
    为什么Git比其他版本控制系统设计得优秀,因为Git跟踪并管理的是修改,而非文件。
    当你完成“论文-一稿”并git add到暂存区之后,你可以通过git status查看状态。本来准备一气呵成定稿commit之后定稿的,结果论文老师突然直接叫改,于是在工作区把论文修改成了“论文-二稿”。这个时候你直接保存然后commit了!结果你在定稿的论文(master)里发现,还是原来的一稿版本,所以这就是在工作流程里提到的问题,要在二稿修改完git add覆盖上一次暂存区的内容之后再git commit

  • 工作区的回退
    在你commit论文一稿之后,导师看完让你修改了二稿。结果你改完正准备要上传的时候发现:复制粘贴来的段落乱了。这时候你可以慢慢修改,如果用git status查看一下就会提示你:

    $ git status
    On branch master
    Changes not staged for commit:
    (use “git add …” to update what will be committed)
    (use “git checkout -- …” to discard changes in working directory)

    modified: XXXXXX

    no changes added to commit (use “git add” and/or “git commit -a”)

    Git提示使用git checkout -- <file>可以丢弃工作区的修改,也就是说:

  1. 如果你没有把乱码的二稿add进暂存区,那么你的文件将被撤销修改成commit的一稿。
  2. 如果你之前把正常的二稿add进了暂存区,而发现手中工作区二稿的乱码是你乱按导致的,那么在执行指令后,文件将被修改成暂存区里正常的二稿。
    两种情况下工作区的文件都被丢弃了,并且优先去取暂存区的来替换。(说明论文不给导师看都有可能白给)
  • 文件的删除
    可以手动删除或者git rm xxx来删除文件,但是删除的是工作区的文件,如果想更改已经commit的文件时:
    先在工作区用rm xxx删掉文件,这时候可以用git status命令看到提示说工作区和版本库不一致了。如果确实要删除则使用git rm xxx删除,然后git commit确认。

    注意:使用rm只会在工作区删除,而git rm是将暂存区的文件删除,建议执行操作时保持一致。

远程仓库

之前说过在本地有一个工作区和git库,而远程仓库就好比是一个大的货物中转中心。每台电脑的工作区就像是生产线,把生产好的产品放到本地的库里面,然后通过git这个运输线传递。平常自己销售货物的时候可以从自己的仓库里面取,缺货的时候就从大中转中心调货,而这个中转中心就是一个大的git库。所以有了github这个著名的大仓库以供使用,任何人都可以看到。
首先创建好自己的SSH KEY:ssh-keygen -t rsa -C "youremail@example.com",在.ssh目录里,有id_rsair_rsa.pub这个密码对,id_rsa是私钥,不能泄露出去,id_rsa.pub是公钥,可以放心地告诉任何人。

  • 上传到远程库
    首先现在github上创建一个repository,然后执行git push <远程主机名> <本地分支名>:<远程分支名>将之与本地库链接。远程主机名默认origin,如果省略远程分支名,则表示将本地分支推送到与之存在”追踪关系”的远程分支,如果该远程分支不存在,则会被新建。可以使用git push -u来设置这个“追踪关系”。之后就可以用git push把本地库的内容推送到远程库了。
    当第一次使用git的命令时,会得到一个警告:

    The authenticity of host ‘github.com (xx.xx.xx.xx)’ can’t be established.
    RSA key fingerprint is xx.xx.xx.xx.xx.
    Are you sure you want to continue connecting (yes/no)?

    这是在验证ssh的key时让你进行确认,然后将本机添加到信任列表之中。

  • 从远程库下载
    当我们关联好远程库之后,可以使用git pull是将以远程库为模板更新本地库,而使用git clone也可以将远程库的文件完全复制到本地,但是不需要连接到本地库也可以直接使用。

分支管理

分支管理就像是开设了多条不同流水线去合并生产一件产品,同时进行互不影响。

  • 分支的合并
    在git库中,每个版本串成了一条时间线。就好比你拥有一个时光机,能来回的穿梭历史但不能去到未来,因为未来还没有确定下来。而分支是什么?比如你写好了一篇初稿论文让老师检阅,在这个不确定的情况下就是一个分支。老师想修改成A版本或者B版本,这时候老师先选了A版本定稿了就是A分支。这时候你坐了时光机又去找老师,这次老师选了B版本,这就是版本B,在两个次元互不影响。后来你发现这AB两个版本定稿的时候改成了同样的C版本,那么C就是分支的合并。
    分支合并可以使用git merge命令用于合并指定分支到当前分支。例如你在A这条线定稿了,然后直接git merge B把B线路也直接快进到C,然后使用git branch显示只有一个C(master)分支了。
    关于分支的切换,我们可以使用git checkout实现,但是因为容易和回溯混淆,建议使用git switch以作区分,添加-c参数可以创建新分支并同时切换。
    但是如果分支B最后定稿的论文是D版本,那么合并的时候C和D就会冲突,将无法合并成到一条时间线上。可以使用git status查看冲突的位置,也可以用git log查看合并的情况(添加–graph可以看到合并图)。

  • *通常,合并分支时Git会用Fast forward模式,但这种模式下,删除分支后,会丢掉分支信息。如果使用了merge --no-ff,则会禁用默认的fast forward模式,而在实际开发时会保留多条线同时进行,定期合并**

  • 分支的临时修订
    我们在工作区工作的时候需要临时切换分支怎么办,可以使用git stash来把工作区临时存储起来,就像在草稿纸上写运算一样,计算到中途临时撕下来一页放在一边。事情做完之后可以使用git stash pop来把草稿纸上的计算滕到本子上来,然后扔掉草稿。如果撕掉的太多,就可以用git stash list从纸堆里找看有哪些便签。而你刚刚发现你做的工作会影响到我这个工作区内容,又不想重新做工作怎么办?使用git cherry-pick来把刚刚的版本号的变动再工作区再做一次。如果分支写了合并之前不想要了,就使用git branch -D来删除分支。

  • 远程库的分支
    与远程仓库连接后可以使用git remote查看远程库信息,或者添加-v参数查看更详细信息。在之前上传时说到远程库默认名为origin,然后使用git push <远程主机名> <远程分支名>来推送到指定位置。而再另一个机器上抓取分支时,只能看到主分支master,但是如果要使用其他分支例如dev上开发,就必须创建远程库的dev分支到本地。首先创建本地dev分支:$ git checkout -b dev origin/dev然后再push到远程dev分支,如果两次提交冲突就可以先使用git pull拉取最新的dev合并后再推送。在首次下拉之前会根据提示设置本地dev和远程库dev的链接:

    $ git pull
    There is no tracking information for the current branch.
    Please specify which branch you want to merge with.
    See git-pull(1) for details.
    git pull
    If you wish to set tracking information for this branch you can do so with:
    git branch --set-upstream-to=origin/ dev

  • Rebase
    如果在多端开发时,在提交改动时会发现有文件冲突,所以会再使用git pull拉取最新的远程库内容以更新,然后再提交本地库。这时候问题就出现了:提交的文件会在pull之后形成新的分支(因为一个是在本地基础上更新的,一个是在pull之后更新的,就类似于起跑线不一样),使用git log可以查看,这样明明在一条时间线上做修改但是最后变成了2条时间线。所以在修改完之后可以使用git rebase将时间线合为一条直线,就相当于把pull下来的文件当作你修改之前的样本了,所以不会产生历史分支了。

标签管理

标签实际上就是给不同的提交取上别名,是一个指向每次commit的一个自定义指针。

  • 创建标签
    首先切换到需要创建标签的分支上,然后使用git tag <标签名>来创建,如果想指定到任意一次commit,就在后面添加一个可辨识的commit id即可,然后使用git tag来查看全部标签,然后git show <标签名>来查看标签的详细信息。如果想创建更详细的标签,使用-a指定标签名,-m指定备注信息,例如git -a xx -m xx <commit id>

  • 管理标签
    如果想要删除标签,使用git tag -d <标签名>来删除指定标签。如果想指定推送特定的commit,那么使用git tag origin <标签名>,或者直接--tags推送所有标签。但是如果推送之后想在远程库删除标签,就要现在本地删除之后再执行git push origin :refs/tags/<tagname>

扩展文件

关于一些git的配置内容,例如git config --global color.ui true添加颜色,提高工作效率。

  • 忽略文件
    在本地开发提交时,git会将所有内容上传至远程库。但这时需要忽略一部分文件(例如隐私、副本)的话,在git目录下创建一个.gitignore文件来配置忽略上传的清单。github上有大量模板使用:https://github.com/github/gitignore
    如果发现添加文件到git不成功,可能时是被.gitignore忽略了,可以使用git check-ignore来检查,然后使用!+文件名来反选特殊的文件,或者用git add -f xxx来强制添加到git库。
  • 配置文件
    如果想配置git相关内容,可以在.git/config文件中找到。其中[alias]是别名配置,可以使用git config (--global) alias.XXX '命令'来为当前命令,设置名为XX的别名,之后可以使用git XXX来代替git 命令来提高效率了。

资源相关

内容引用:廖雪峰的官方网站 以及 评论区的小伙伴
国外网友制作的pdf:git cheat sheet