0%

Git常用命令总结

1.初始化本地仓库

1
git init

2.添加文件到本地仓库暂存区

1
git add a.txt

3.添加文件到本地仓库

1
git commit -m 'v1'

此命令代表确认提交到本地仓库。-m ‘v1’代表为此添加一个版本标记 v1 4.查看当前 git 的状态

1
git status

结果 A:

1
2
3
4
5
6
7
8
On branch master
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working directory)

modified: readme.txt

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

证明当前有文件已经修改,但是没有准备提交的修改,没有 add 和 commit 结果 B:

1
2
3
4
5
 On branch master
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)

modified: readme.txt

证明当前已经有文件提交了,但是还没有 commit 结果 C:

1
2
On branch master
nothing to commit, working directory clean

证明当前所有文件已经提交到本地仓库,工作目录是干净的 5.查看 git 日志

1
git log

结果:

1
2
3
4
5
6
7
8
9
10
11
commit aca3fe6cc3f49ded922d05e4774561f33697f710
Author: Qingcai Cui <1016903103@qq.com>
Date: Sun Nov 2 12:16:25 2014 +0800

v2

commit 90eea044b6da3818770ec482df98bb05ab569472
Author: Qingcai Cui <1016903103@qq.com>
Date: Sun Nov 2 12:07:46 2014 +0800

v1

证明当前我们已经 commit 了两次,上面的为最近提交的。 如果嫌输出太多可以尝试下面的命令,一行显示

1
git log --pretty=oneline

结果如下:

1
2
aca3fe6cc3f49ded922d05e4774561f33697f710 v2
90eea044b6da3818770ec482df98bb05ab569472 v1

一大串类似的

1
aca3fe6cc3f49ded922d05e4774561f33697f710

是 commit id(版本号),和 SVN 不一样,Git 的 commit id 不是 1,2,3……递增的数字,而是一个 SHA1 计算出来的一个非常大的数字,用十六进制表示,而且你看到的 commit id 和我的肯定不一样,以你自己的为准。为什么 commit id 需要用这么一大串数字表示呢?因为 Git 是分布式的版本控制系统,后面我们还要研究多人在同一个版本库里工作,如果大家都用 1,2,3……作为版本号,那肯定就冲突了。 6.版本回退 回退到上一版本:

1
git reset --hard HEAD^

回退到上上个版本:

1
git reset --hard HEAD^^

如果回退的版本过多则不用加那么多的^号 比如回退到上 10 版本,则可以用下面的命令

1
git reset --hard HEAD~10

回退 1 个版本相当于

1
git reset --hard HEAD~1

不过现在利用 git status 来查看已经看不到刚才那个版本了,想要返回的话怎么办 可以仍然用上面的方法

1
git reset --hard aca3f

只要写前几位就好了,git 会自动去匹配的。当然前提是你的命令行窗口没有关闭还能找到之前的 commit id。 不过万一你的命令行关闭了也没关系,git 提供了一个方法来记录你的每一次命令。

1
git reflog

结果:

1
2
3
4
aca3fe6 HEAD@{0}: reset: moving to aca3f
90eea04 HEAD@{1}: reset: moving to HEAD^
aca3fe6 HEAD@{2}: commit: jj
90eea04 HEAD@{3}: commit (initial): aa

在前方仍然显示了版本号,你仍然可以找到。仍然可以利用的 reset 命令来还原。 注意: A 工作区和暂存区的名词区别 工作区:就是你在电脑里能看到的目录 暂存区:在.git 文件夹下存在一个暂存区 stage 和好多个分支比如 master 当执行 git add 命令时,工作区的内容便会到 stage 暂存区中,当执行 git commit 命令时暂存区的内容便会提交到分支里面。 B “Git 管理的是修改”的意思 比如第一次修改 readme.txt,然后执行 git add 到暂存区,然后再修改 readme.txt,然后执行 git commit 到分支。 结果调用 git status 时发现现在仍然有一个 modified 文件,这是因为我们没有把新修改的文件提交到暂存区,所以导致分支中的文件和在工作区的原文不匹配。所以我们需要重新 add 和 commit。这说明 git 管理的是”修改”,而不是”文件”本身。 7.撤销修改

1
git checkout -- filename

比如 git checkout — readme.txt 它的作用如下: 把 readme.txt 文件在工作区的修改全部撤销,这里有两种情况: 一种是 readme.txt 自修改后还没有被放到暂存区,现在,撤销修改就回到和版本库一模一样的状态; 一种是 readme.txt 已经添加到暂存区后,又作了修改,现在,撤销修改就回到添加到暂存区后的状态。 总之,就是让这个文件回到最近一次 git commit 或 git add 时的状态。 那么上面的这个情况是我们提交或者没提交到暂存区之后又对源文件做的修改。 还有另一种情况,我们提交之后放到了暂存区,我们想把暂存区里面的文件撤销回来。 就用以下命令:

1
git reset HEAD readme.txt

就是将刚才的 git add 命令撤销,把暂存区中的内容撤销回到工作区。 当然,如果你不但 add 了,并且又 commit 了,那就只能进行版本回退了。在上面已经说过了。 总结: 场景 1:当你改乱了工作区某个文件的内容,想直接丢弃工作区的修改时,用命令 git checkout — file。 场景 2:当你不但改乱了工作区某个文件的内容,还添加到了暂存区时,想丢弃修改,分两步,第一步用命令 git reset HEAD file,就回到了场景 1,第二步按场景 1 操作。 场景 3:已经提交了不合适的修改到版本库时,想要撤销本次提交,进行版本回退,不过前提是没有推送到远程库。 8.删除文件 假如现在你新建了一个 hello.txt 文件,你已经 add 并 commit 到了本地分支之中。 现在你想删除,如果直接执行

1
rm hello.txt

则是只把工作区中的文件删除了,本地分支中没有删除,现在你执行 git status 则会提示当前工作区已删除了一个文件,本地分支仍然存在,就存在了工作区和本地分支不同步的问题,现在我们如果想恢复一下,就利用下面的命令

1
git checkout -- hello.txt

将本地的文件一键还原。 假如我们真的是想将本地分支中的一个文件删除,那么我们就执行下面的方法。

1
git rm hello.txt

执行了这个命令之后,我们执行 git status 之后就会提示 你现在需要 commit 一下确认删除。 并且执行完这个命令之后,我们执行 ls 命令之后发现本地的文件也已经不存在了。 如果有很多个文件在本地被删除掉了,暂存区和工作区的文件完全不一样了,工作区删除掉了很多个文件,就会出现

1
2
3
Changes not staged for commit:
deleted: a.txt
deleted: b.txt

如果一个个地删除文件肯定特别麻烦,所以我们可以用下面的命令来

1
git add -A

它等同于 git add . 和 git add -u

1
git add . 保存所有新文件和改动的文件,不包括删除的文件
1
git add -u  保存所有改动的文件和删除的文件,不包括新的文件

git add -A 和 git add -u 会把我们未通过 git rm 删除的文件全部 stage 使用过以后运行 git status 便会出现 changes to be committed … 说明已经都经过 git rm 删除了. 综上,我们想删除分支中的文件时就需要两条命令合起来使用

1
2
git rm hello.txt
git commit -m 'rm hello.txt'

要小心的是,执行 git rm 方法之后工作区和本地分支中的文件已经都不存在了。所以如果你已经在远程仓库存在备份的话,你就不用担心误删了。否则你就要小心了,会丢失这个文件的。 对比修改的文件

1
git diff

结果:

1
2
3
4
5
6
7
diff --git a/readme.txt b/readme.txt
index 9c58532..8ce5f7e 100644
--- a/readme.txt
+++ b/readme.txt
@@ -1 +1 @@
-git is grea
+hello is grea

-号开头的语句代表这句话删除掉了 +号开头的语句代表这句话为新增语句 9.分支 新建本地分支

1
git branch dev

切换到 dev 分支

1
git checkout dev

创建并切换到该分支

1
git checkout -b dev

查看本地分支

1
git branch

比如此命令会输出 * master hello 代表当前已经选中了 master 分支,存在本地两个分支 master 和 hello 合并分支

1
2
git branch master
git merge hello

这样我们就把 master 分支合并到了 hello 分支了。 接下来我们就可以删除本地分支了。 既然分支合并这么简单,它可不可能出现什么问题呢?当然有,当然会出现分支合并冲突的问题。 比如我切换到了 hello 分支并修改了一个文件 add 并且 commit,然后我切换回了 master 分支 同样修改了这个文件,add 并且 commit。现在我们如果执行 git merge hello 则会报一个提示说 分支合并冲突。 我们查看刚才修改的文件发现已经发生了变化,我们需要手动修改完了之后,然后继续 add 和 commit 才可以。如果没有 add 和 commit,那么我们无法切换回原来的分支的。 add 和 commit 之后,原来的 hello 分支仍然保持了原来不变,只不过是我们的 master 分支改变了。下面示意图则清楚地表示出了如下关系,图中的 feature1 相当于 hello 分支。 合并之后,我们就可以进行删除分支了,可以删除掉 hello 分支。 0 其实上面的一系列操作 从 merge 到修改 然后 add 然后 commit 其实可以利用一条命令来修改,这个方法叫禁用 Fast Forward 模式 刚才的一系列命令如下

1
2
3
4
5
git checkout master
git merge hello
vi file.txt
git add file.txt
git commit -m 'merge master'

那么利用下面的语句同样可以达成同样的效果

1
2
git checkout master
git merge --no-ff -m 'merge master' hello

因为本次合并要创建一个新的 commit,所以加上 -m 参数,把 commit 描述写进去。 Git 就会在 merge 时生成一个新的 commit,这样,从分支历史上就可以看出分支信息。 结束之后我们照样可以删除 hello 分支。 删除本地分支

1
git branch -d hello

查看远程分支

1
git branch -r

查看本地和远程分支

1
git branch -a

现在遇到一个问题,我们正在工作的一个分支还没有做完,不能 add 或者 commit,但是现在有一个 bug 需要在另一个分支上去修复,那么我们就需要暂时存储当前的分支。所以就要用到下面的命令

1
git stash

当我们处理完其他的事情之后,再切换回来此分支。 先使用

1
git stash list

再取出 stash 列表中的内容

1
git stash pop

上面的方法既取出了 list 内容,并且把 list 中的元素删除掉。 强行删除分支

1
git branch -D new-branch

10.多人协作 多人协作的工作模式通常是这样: 首先,可以试图用

1
git push origin branch-name

推送自己的修改; 如果推送失败,则因为远程分支比你的本地更新,需要先用 git pull 试图合并; 如果合并有冲突,则解决冲突,并在本地提交; 没有冲突或者解决掉冲突后,再用

1
git push origin branch-name

推送就能成功! 如果 git pull 提示“no tracking information”,则说明本地分支和远程分支的链接关系没有创建,用命令

1
git branch --set-upstream branch-name origin/branch-name

这就是多人协作的工作模式,一旦熟悉了,就非常简单。 11.添加远程地址别名

1
git remote add origin git@github.com

删除远程地址别名

1
git remote rm origin

此方法删除掉 origin 这个地址别名 查看远程地址别名

1
git remote -v

推送到远程分支 我们在 github 上新建一个项目 添加远程仓库

1
git remote add origin  git@github.com:cqcre/gittest.git

推送上去

1
git push -u origin master

加上了 -u 参数,Git 不但会把本地的 master 分支内容推送的远程新的 master 分支,还会把本地的 master 分支和远程的 master 分支关联起来,即相当于推送到了一个默认的分支,在以后的推送或者拉取时就可以简化命令。 那么以后我们就不需要关联了,以后推送的话我们只需要输入

1
git push origin master

克隆远程仓库 假设现在已经存在了一个远程仓库,我们需要把这个仓库克隆到本地,我们需要使用下面的方法

1
git clone git@github.com:cqcre/test.git

这样我们就把远程的一个仓库取到了本地了。 12.强制操作 强制覆盖本地分支内容

1
2
git fetch --all
git reset --hard origin/master

强制覆盖远程内容

1
git push origin master --force

13.修改 commit 的备注 有时候我们 commit 的备注写错了,需要重新修改,可以利用如下命令

1
git commit --amend

14. .gitignore 的使用 在 git 中如果想忽略掉某个文件,不让这个文件提交到版本库中,可以使用修改根目录中 .gitignore 文件的方法(如无,则需自己手工建立此文件)。这个文件每一行保存了一个匹配的规则例如:

1
2
3
4
5
*.a # 忽略所有 .a 结尾的文件
!lib.a # 但 lib.a 除外
/TODO # 仅仅忽略项目根目录下的 TODO 文件,不包括 subdir/TODO
build/ # 忽略 build/ 目录下的所有文件
doc/*.txt # 会忽略 doc/notes.txt 但不包括 doc/server/arch.txt

规则很简单,不做过多解释,但是有时候在项目开发过程中,突然心血来潮想把某些目录或文件加入忽略规则,按照上述方法定义后发现并未生效,原因是.gitignore 只能忽略那些原来没有被 track 的文件,如果某些文件已经被纳入了版本管理中,则修改.gitignore 是无效的。那么解决方法就是先把本地缓存删除(改变成未 track 状态),然后再提交:

1
2
3
git rm -r --cached .
git add .
git commit -m 'update .gitignore'

15. 打 tag 在发布版本的时候,经常会用到打标签的方法。 增加一个标签

1
git tag -a "v1.0.0" -m "Version 1.0.0"

删除一个标签

1
git tag -d v1.0.0

删除远程标签

1
git push --delete origin v1.0.0

推送所有标签

1
git push origin --tags

16. 删除未监视文件

1
2
3
4
5
6
7
8
9
10
11
12
git clean -f

# 连 untracked 的目录也一起删掉
git clean -fd

# 连 gitignore 的untrack 文件/目录也一起删掉 (慎用,一般这个是用来删掉编译出来的 .o之类的文件用的)
git clean -xfd

# 在用上述 git clean 前,墙裂建议加上 -n 参数来先看看会删掉哪些文件,防止重要文件被误删
git clean -nxfd
git clean -nf
git clean -nfd

17. 子模块

1
2
3
4
5
git clone <repository> --recursive 递归的方式克隆整个项目
git submodule add <repository> <path> 添加子模块
git submodule init 初始化子模块
git submodule update 更新子模块
git submodule foreach git pull 拉取所有子模块