参考
Git教程
创建一个云端仓库
git init
git add README.md
git commit -m "first commit"
git remote add origin https://github.com/Monster1164/Django-.git
git push -u origin master
git 常用命令表
设置自己地址账号和邮箱
$ git config --global user.name "Your Name"
$ git config --global user.email "email@example.com"
- 注意 git config 命令的–global 参数,用了这个参数,表示你这台机器上所有的 Git 仓库都会使用这个配置,当然也可以对某个仓库指定不同的用户名和 Email 地址
创建版本库
$ git init
第一步,用命令git add
告诉 Git,把文件添加到仓库:
$ git add readme.txt
第二步,用命令git commit
告诉 Git,把文件提交到仓库:
$ git commit -m "wrote a readme file"
[master (root-commit) eaadf4e] wrote a readme file
1 file changed, 2 insertions(+)
create mode 100644 readme.txt
- 要随时掌握工作区的状态,使用
git status
命令。 - 如果
git status
告诉你有文件被修改过,用git diff
可以查看修改内容。
版本回退
总结:
现在总结一下:
HEAD
指向的版本就是当前版本,因此,Git 允许我们在版本的历史之间穿梭,使用命令git reset --hard commit_id
。- 穿梭前,用
git log
可以查看提交历史,以便确定要回退到哪个版本。 - 要重返未来,用
git reflog
查看命令历史,以便确定要回到未来的哪个版本。
查看版本
在 Git 中,我们用git log
命令查看:
$ git log
commit 1094adb7b9b3807259d8cb349e7df1d4d6477073 (HEAD -> master)
Author: Michael Liao <askxuefeng@gmail.com>
Date: Fri May 18 21:06:15 2018 +0800
append GPL
commit e475afc93c209a690c39c13a46716e8fa000c366
Author: Michael Liao <askxuefeng@gmail.com>
Date: Fri May 18 21:03:36 2018 +0800
add distributed
commit eaadf4e385e865d25c48e7ca9c8395c3f7dfaef0
Author: Michael Liao <askxuefeng@gmail.com>
Date: Fri May 18 20:59:18 2018 +0800
wrote a readme file
git log
命令显示从最近到最远的提交日志,我们可以看到 3 次提交,最近的一次是append GPL
,上一次是add distributed
,最早的一次是wrote a readme file
。
如果嫌输出信息太多,看得眼花缭乱的,可以试试加上--pretty=oneline
参数:
回退版本
git reset
命令:
首先,Git 必须知道当前版本是哪个版本,在 Git 中,用HEAD
表示当前版本,也就是最新的提交1094adb...
(注意我的提交 ID 和你的肯定不一样),上一个版本就是HEAD^
,上上一个版本就是HEAD^^
,当然往上 100 个版本写 100 个^
比较容易数不过来,所以写成HEAD~100
。
现在,我们要把当前版本append GPL
回退到上一个版本add distributed
,就可以使用git reset
命令:
$ git reset --hard HEAD^
HEAD is now at e475afc add distributed
--hard
参数有啥意义?这个后面再讲,现在你先放心使用。
记录每一次命令
Git 提供了一个命令git reflog
用来记录你的每一次命令:
工作区和暂存区
工作区(Working Directory)
就是你在电脑里能看到的目录,比如我的learngit
文件夹就是一个工作区:
版本库(Repository)
工作区有一个隐藏目录.git
,这个不算工作区,而是 Git 的版本库。
Git 的版本库里存了很多东西,其中最重要的就是称为 stage(或者叫 index)的暂存区,还有 Git 为我们自动创建的第一个分支master
,以及指向master
的一个指针叫HEAD
。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qG7NlIhJ-1624589124260)(Git.assets/0.jpeg)]
第一步是用git add
把文件添加进去,实际上就是把文件修改添加到暂存区;
第二步是用git commit
提交更改,实际上就是把暂存区的所有内容提交到当前分支。
管理修改
因为 Git 跟踪并管理的是修改,而非文件。
撤销修改
修改工作区的修改
命令git checkout -- readme.txt
意思就是,把readme.txt
文件在工作区的修改全部撤销,这里有两种情况:
一种是readme.txt
自修改后还没有被放到暂存区,现在,撤销修改就回到和版本库一模一样的状态;
一种是readme.txt
已经添加到暂存区后,又作了修改,现在,撤销修改就回到添加到暂存区后的状态。
总之,就是让这个文件回到最近一次git commit
或git add
时的状态。
git checkout -- file
命令中的--
很重要,没有--
,就变成了“切换到另一个分支”的命令,我们在后面的分支管理中会再次遇到git checkout
命令。
修改缓冲区的修改
Git 同样告诉我们,用命令git reset HEAD <file>
可以把暂存区的修改撤销掉(unstage),重新放回工作区:
$ git reset HEAD readme.txt
Unstaged changes after reset:
M readme.txt
git reset
命令既可以回退版本,也可以把暂存区的修改回退到工作区。当我们用HEAD
时,表示最新的版本。
删除文件
一般情况下,你通常直接在文件管理器中把没用的文件删了,或者用rm
命令删了:
$ rm test.txt
这个时候,Git 知道你删除了文件,因此,工作区和版本库就不一致了。
现在你有两个选择,一是确实要从版本库中删除该文件,那就用命令git rm
删掉,并且git commit
:
$ git rm test.txt
rm 'test.txt'
$ git commit -m "remove test.txt"
[master d46f35e] remove test.txt
1 file changed, 1 deletion(-)
delete mode 100644 test.txt
现在,文件就从版本库中被删除了。
另一种情况是删错了,因为版本库里还有呢,所以可以很轻松地把误删的文件恢复到最新版本:
$ git checkout -- test.txt
git checkout
其实是用版本库里的版本替换工作区的版本,无论工作区是修改还是删除,都可以“一键还原”。
远程仓库
实际情况往往是这样,找一台电脑充当服务器的角色,每天 24 小时开机,其他每个人都从这个“服务器”仓库克隆一份到自己的电脑上,并且各自把各自的提交推送到服务器仓库里,也从服务器仓库中拉取别人的提交。
要关联一个远程库,使用命令git remote add origin git@server-name:path/repo-name.git
;
关联一个远程库时必须给远程库指定一个名字,origin
是默认习惯命名;
关联后,使用命令git push -u origin master
第一次推送 master 分支的所有内容;
此后,每次本地提交后,只要有必要,就可以使用命令git push origin master
推送最新修改;
创建 SSH Key
第 1 步:创建 SSH Key。在用户主目录下,看看有没有.ssh 目录,如果有,再看看这个目录下有没有id_rsa
和id_rsa.pub
这两个文件,如果已经有了,可直接跳到下一步。如果没有,打开 Shell(Windows 下打开 Git Bash),创建 SSH Key:
$ ssh-keygen -t rsa -C "youremail@example.com"
你需要把邮件地址换成你自己的邮件地址,然后一路回车,使用默认值即可,由于这个 Key 也不是用于军事目的,所以也无需设置密码。
如果一切顺利的话,可以在用户主目录里找到.ssh
目录,里面有id_rsa
和id_rsa.pub
两个文件,这两个就是 SSH Key 的秘钥对,id_rsa
是私钥,不能泄露出去,id_rsa.pub
是公钥,可以放心地告诉任何人。
第 2 步:登陆 GitHub,打开“Account settings”,“SSH Keys”页面:
然后,点“Add SSH Key”,填上任意 Title,在 Key 文本框里粘贴id_rsa.pub
文件的内容:
点“Add Key”,你就应该看到已经添加的 Key:
添加远程库
现在,我们根据 GitHub 的提示,在本地的learngit
仓库下运行命令:
$ git remote add origin git@github.com:michaelliao/learngit.git
请千万注意,把上面的michaelliao
替换成你自己的 GitHub 账户名,否则,你在本地关联的就是我的远程库,关联没有问题,但是你以后推送是推不上去的,因为你的 SSH Key 公钥不在我的账户列表中。
添加后,远程库的名字就是origin
,这是 Git 默认的叫法,也可以改成别的,但是origin
这个名字一看就知道是远程库。
下一步,就可以把本地库的所有内容推送到远程库上:
$ git push -u origin master
Counting objects: 20, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (15/15), done.
Writing objects: 100% (20/20), 1.64 KiB | 560.00 KiB/s, done.
Total 20 (delta 5), reused 0 (delta 0)
remote: Resolving deltas: 100% (5/5), done.
To github.com:michaelliao/learngit.git
* [new branch] master -> master
Branch 'master' set up to track remote branch 'master' from 'origin'.
把本地库的内容推送到远程,用git push
命令,实际上是把当前分支master
推送到远程。
由于远程库是空的,我们第一次推送master
分支时,加上了-u
参数,Git 不但会把本地的master
分支内容推送的远程新的master
分支,还会把本地的master
分支和远程的master
分支关联起来,在以后的推送或者拉取时就可以简化命令。
从现在起,只要本地作了提交,就可以通过命令:
$ git push origin master
把本地master
分支的最新修改推送至 GitHub,现在,你就拥有了真正的分布式版本库!
删除远程库
如果添加的时候地址写错了,或者就是想删除远程库,可以用git remote rm <name>
命令。使用前,建议先用git remote -v
查看远程库信息:
$ git remote -v
origin git@github.com:michaelliao/learn-git.git (fetch)
origin git@github.com:michaelliao/learn-git.git (push)
然后,根据名字删除,比如删除origin
:
$ git remote rm origin
此处的“删除”其实是解除了本地和远程的绑定关系,并不是物理上删除了远程库。远程库本身并没有任何改动。要真正删除远程库,需要登录到 GitHub,在后台页面找到删除按钮再删除。
从远程库克隆
上次我们讲了先有本地库,后有远程库的时候,如何关联远程库。
现在,假设我们从零开发,那么最好的方式是先创建远程库,然后,从远程库克隆。
首先,登陆 GitHub,创建一个新的仓库,名字叫gitskills
:
现在,远程库已经准备好了,下一步是用命令git clone
克隆一个本地库:
$ git clone git@github.com:michaelliao/gitskills.git
Cloning into 'gitskills'...
remote: Counting objects: 3, done.
remote: Total 3 (delta 0), reused 0 (delta 0), pack-reused 3
Receiving objects: 100% (3/3), done.
注意把 Git 库的地址换成你自己的,然后进入gitskills
目录看看,已经有README.md
文件了:
分支管理
小结
- Git 鼓励大量使用分支:
查看分支:git branch
创建分支:git branch <name>
切换分支:git checkout <name>
或者git switch <name>
创建+切换分支:git checkout -b <name>
或者git switch -c <name>
合并某分支到当前分支:git merge <name>
删除分支:git branch -d <name>
- 快合并分支
# 1. 切换到当前分支
git switch master
# 2. 合并某分支到当前分支
git merge dev(某分支)
创建与合并分支
在版本回退里,你已经知道,每次提交,Git 都把它们串成一条时间线,这条时间线就是一个分支。截止到目前,只有一条时间线,在 Git 里,这个分支叫主分支,即master
分支。HEAD
严格来说不是指向提交,而是指向master
,master
才是指向提交的,所以,HEAD
指向的就是当前分支。
一开始的时候,master
分支是一条线,Git 用master
指向最新的提交,再用HEAD
指向master
,就能确定当前分支,以及当前分支的提交点:
每次提交,master
分支都会向前移动一步,这样,随着你不断提交,master
分支的线也越来越长。
当我们创建新的分支,例如dev
时,Git 新建了一个指针叫dev
,指向master
相同的提交,再把HEAD
指向dev
,就表示当前分支在dev
上:
你看,Git 创建一个分支很快,因为除了增加一个dev
指针,改改HEAD
的指向,工作区的文件都没有任何变化!
不过,从现在开始,对工作区的修改和提交就是针对dev
分支了,比如新提交一次后,dev
指针往前移动一步,而master
指针不变:
假如我们在dev
上的工作完成了,就可以把dev
合并到master
上。Git 怎么合并呢?最简单的方法,就是直接把master
指向dev
的当前提交,就完成了合并:
所以 Git 合并分支也很快!就改改指针,工作区内容也不变!
合并完分支后,甚至可以删除dev
分支。删除dev
分支就是把dev
指针给删掉,删掉后,我们就剩下了一条master
分支:
真是太神奇了,你看得出来有些提交是通过分支完成的吗?
下面开始实战。
首先,我们创建dev
分支,然后切换到dev
分支:
$ git checkout -b dev
Switched to a new branch 'dev'
git checkout
命令加上-b
参数表示创建并切换,相当于以下两条命令:
$ git branch dev # 创建分支
$ git checkout dev # 切换分支
Switched to branch 'dev'
然后,用git branch
命令查看当前分支:
$ git branch
* dev
master
然后,用git branch
命令查看当前分支:
$ git branch
* dev
master
git branch
命令会列出所有分支,当前分支前面会标一个*
号。
现在,我们把dev
分支的工作成果合并到master
分支上:
$ git checkout master
$ git merge dev
Updating d46f35e..b17d20e
Fast-forward
readme.txt | 1 +
1 file changed, 1 insertion(+)
git merge
命令用于合并指定分支到当前分支。合并后,再查看readme.txt
的内容,就可以看到,和dev
分支的最新提交是完全一样的。
注意到上面的Fast-forward
信息,Git 告诉我们,这次合并是“快进模式”,也就是直接把master
指向dev
的当前提交,所以合并速度非常快
switch
我们注意到切换分支使用git checkout <branch>
,而前面讲过的撤销修改则是git checkout -- <file>
,同一个命令,有两种作用,确实有点令人迷惑。
实际上,切换分支这个动作,用switch
更科学。因此,最新版本的 Git 提供了新的git switch
命令来切换分支:
创建并切换到新的dev
分支,可以使用:
$ git switch -c dev
直接切换到已有的master
分支,可以使用:
$ git switch master
使用新的git switch
命令,比git checkout
要更容易理解。
解决冲突
总结:
当 Git 无法自动合并分支时,就必须首先解决冲突。解决冲突后,再提交,合并完成。
解决冲突就是把 Git 合并失败的文件手动编辑为我们希望的内容,再提交。
用git log --graph
命令可以看到分支合并图。
人生不如意之事十之八九,合并分支往往也不是一帆风顺的。
准备新的feature1
分支,继续我们的新分支开发:
$ git switch -c feature1
Switched to a new branch 'feature1'
修改readme.txt
最后一行,改为:
Creating a new branch is quick AND simple.
在feature1
分支上提交:
$ git add readme.txt
$ git commit -m "AND simple"
[feature1 14096d0] AND simple
1 file changed, 1 insertion(+), 1 deletion(-)
切换到master
分支:
$ git switch master
Switched to branch 'master'
Your branch is ahead of 'origin/master' by 1 commit.
(use "git push" to publish your local commits)
Git 还会自动提示我们当前master
分支比远程的master
分支要超前 1 个提交。
在master
分支上把readme.txt
文件的最后一行改为:
Creating a new branch is quick & simple.
提交:
$ git add readme.txt
$ git commit -m "& simple"
[master 5dc6824] & simple
1 file changed, 1 insertion(+), 1 deletion(-)
现在,master
分支和feature1
分支各自都分别有新的提交,变成了这样:
这种情况下,Git 无法执行“快速合并”,只能试图把各自的修改合并起来,但这种合并就可能会有冲突,我们试试看:
$ git merge feature1
Auto-merging readme.txt
CONFLICT (content): Merge conflict in readme.txt
Automatic merge failed; fix conflicts and then commit the result.
果然冲突了!Git 告诉我们,readme.txt
文件存在冲突,必须手动解决冲突后再提交。git status
也可以告诉我们冲突的文件:
$ git status
On branch master
Your branch is ahead of 'origin/master' by 2 commits.
(use "git push" to publish your local commits)
You have unmerged paths.
(fix conflicts and run "git commit")
(use "git merge --abort" to abort the merge)
Unmerged paths:
(use "git add <file>..." to mark resolution)
both modified: readme.txt
no changes added to commit (use "git add" and/or "git commit -a")
我们可以直接查看 readme.txt 的内容:
Git is a distributed version control system.
Git is free software distributed under the GPL.
Git has a mutable index called stage.
Git tracks changes of files.
<<<<<<< HEAD
Creating a new branch is quick & simple.
=======
Creating a new branch is quick AND simple.
>>>>>>> feature1
Git 用<<<<<<<
,=======
,>>>>>>>
标记出不同分支的内容,我们修改如下后保存:
Creating a new branch is quick and simple.
再提交:
$ git add readme.txt
$ git commit -m "conflict fixed"
[master cf810e4] conflict fixed
现在,master
分支和feature1
分支变成了下图所示:
用带参数的git log
也可以看到分支的合并情况:
$ git log --graph --pretty=oneline --abbrev-commit
* cf810e4 (HEAD -> master) conflict fixed
|\
| * 14096d0 (feature1) AND simple
* | 5dc6824 & simple
|/
* b17d20e branch test
* d46f35e (origin/master) remove test.txt
* b84166e add test.txt
* 519219b git tracks changes
* e43a48b understand how stage works
* 1094adb append GPL
* e475afc add distributed
* eaadf4e wrote a readme file
最后,删除feature1
分支:
$ git branch -d feature1
Deleted branch feature1 (was 14096d0).
工作完成。
bug 分支
修复 bug 时,我们会通过创建新的 bug 分支进行修复,然后合并,最后删除;
当手头工作没有完成时,先把工作现场git stash
一下,然后去修复 bug,修复后,再git stash pop
,回到工作现场;
在 master 分支上修复的 bug,想要合并到当前 dev 分支,可以用git cherry-pick <commit>
命令,把 bug 提交的修改“复制”到当前分支,避免重复劳动。
强制删除一个分支
开发一个新 feature,最好新建一个分支;
如果要丢弃一个没有被合并过的分支,可以通过git branch -D <name>
强行删除。
多人协作
当你从远程仓库克隆时,实际上 Git 自动把本地的master
分支和远程的master
分支对应起来了,并且,远程仓库的默认名称是origin
。
要查看远程库的信息,用git remote
:
$ git remote
origin
或者,用git remote -v
显示更详细的信息:
$ git remote -v
origin git@github.com:michaelliao/learngit.git (fetch)
origin git@github.com:michaelliao/learngit.git (push)
上面显示了可以抓取和推送的origin
的地址。如果没有推送权限,就看不到 push 的地址。
推送分支
提示:
推送分支,就是把该分支上的所有本地提交推送到远程库。推送时,要指定本地分支,这样,Git 就会把该分支推送到远程库对应的远程分支上:
$ git push origin master
如果要推送其他分支,比如dev
,就改成:
$ git push origin dev
但是,并不是一定要把本地分支往远程推送,那么,哪些分支需要推送,哪些不需要呢?
master
分支是主分支,因此要时刻与远程同步;dev
分支是开发分支,团队所有成员都需要在上面工作,所以也需要与远程同步;- bug 分支只用于在本地修复 bug,就没必要推到远程了,除非老板要看看你每周到底修复了几个 bug;
- feature 分支是否推到远程,取决于你是否和你的小伙伴合作在上面开发。
总之,就是在 Git 中,分支完全可以在本地自己藏着玩,是否推送,视你的心情而定!
总结:
因此,多人协作的工作模式通常是这样:
- 首先,可以试图用
git push origin <branch-name>
推送自己的修改; - 如果推送失败,则因为远程分支比你的本地更新,需要先用
git pull
试图合并; - 如果合并有冲突,则解决冲突,并在本地提交;
- 没有冲突或者解决掉冲突后,再用
git push origin <branch-name>
推送就能成功!
如果git pull
提示no tracking information
,则说明本地分支和远程分支的链接关系没有创建,用命令git branch --set-upstream-to <branch-name> origin/<branch-name>
。
这就是多人协作的工作模式,一旦熟悉了,就非常简单。
- 查看远程库信息,使用
git remote -v
; - 本地新建的分支如果不推送到远程,对其他人就是不可见的;
- 从本地推送分支,使用
git push origin branch-name
,如果推送失败,先用git pull
抓取远程的新提交; - 在本地创建和远程分支对应的分支,使用
git checkout -b branch-name origin/branch-name
,本地和远程分支的名称最好一致; - 建立本地分支和远程分支的关联,使用
git branch --set-upstream branch-name origin/branch-name
; - 从远程抓取分支,使用
git pull
,如果有冲突,要先处理冲突。
你的小伙伴已经向origin/dev
分支推送了他的提交,而碰巧你也对同样的文件作了修改,并试图推送:
$ cat env.txt
env
$ git add env.txt
$ git commit -m "add new env"
[dev 7bd91f1] add new env
1 file changed, 1 insertion(+)
create mode 100644 env.txt
$ git push origin dev
To github.com:michaelliao/learngit.git
! [rejected] dev -> dev (non-fast-forward)
error: failed to push some refs to 'git@github.com:michaelliao/learngit.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.
推送失败,因为你的小伙伴的最新提交和你试图推送的提交有冲突,解决办法也很简单,Git 已经提示我们,先用git pull
把最新的提交从origin/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 <remote> <branch>
If you wish to set tracking information for this branch you can do so with:
git branch --set-upstream-to=origin/<branch> dev
git pull
也失败了,原因是没有指定本地dev
分支与远程origin/dev
分支的链接,根据提示,设置dev
和origin/dev
的链接:
$ git branch --set-upstream-to=origin/dev dev
Branch 'dev' set up to track remote branch 'dev' from 'origin'.
再 pull:
$ git pull
Auto-merging env.txt
CONFLICT (add/add): Merge conflict in env.txt
Automatic merge failed; fix conflicts and then commit the result.
这回git pull
成功,但是合并有冲突,需要手动解决,解决的方法和分支管理中的解决冲突完全一样。解决后,提交,再 push:
$ git commit -m "fix env conflict"
[dev 57c53ab] fix env conflict
$ git push origin dev
Counting objects: 6, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (4/4), done.
Writing objects: 100% (6/6), 621 bytes | 621.00 KiB/s, done.
Total 6 (delta 0), reused 0 (delta 0)
To github.com:michaelliao/learngit.git
7a5e5dd..57c53ab dev -> dev
标签管理
所以,tag 就是一个让人容易记住的有意义的名字,它跟某个 commit 绑在一起。
- 命令
git tag <tagname>
用于新建一个标签,默认为HEAD
,也可以指定一个 commit id; - 命令
git tag -a <tagname> -m "blablabla..."
可以指定标签信息; - 命令
git tag
可以查看所有标签。
自定义 Git
在安装 Git一节中,我们已经配置了user.name
和user.email
,实际上,Git 还有很多可配置项。
比如,让 Git 显示颜色,会让命令输出看起来更醒目:
$ git config --global color.ui true
这样,Git 会适当地显示不同的颜色,比如git status
命令:
文件名就会标上颜色。
我们在后面还会介绍如何更好地配置 Git,以便让你的工作更高效。
忽略特殊文件
有些时候,你必须把某些文件放到 Git 工作目录中,但又不能提交它们,比如保存了数据库密码的配置文件啦,等等,每次git status
都会显示Untracked files ...
,有强迫症的童鞋心里肯定不爽。
好在 Git 考虑到了大家的感受,这个问题解决起来也很简单,在 Git 工作区的根目录下创建一个特殊的.gitignore
文件,然后把要忽略的文件名填进去,Git 就会自动忽略这些文件。
不需要从头写.gitignore
文件,GitHub 已经为我们准备了各种配置文件,只需要组合一下就可以使用了。所有配置文件可以直接在线浏览:https://github.com/github/gitignore
忽略文件的原则是:
- 忽略操作系统自动生成的文件,比如缩略图等;
- 忽略编译生成的中间文件、可执行文件等,也就是如果一个文件是通过另一个文件自动生成的,那自动生成的文件就没必要放进版本库,比如 Java 编译产生的
.class
文件; - 忽略你自己的带有敏感信息的配置文件,比如存放口令的配置文件。
举个例子:
假设你在 Windows 下进行 Python 开发,Windows 会自动在有图片的目录下生成隐藏的缩略图文件,如果有自定义目录,目录下就会有Desktop.ini
文件,因此你需要忽略 Windows 自动生成的垃圾文件:
# Windows:
Thumbs.db
ehthumbs.db
Desktop.ini
然后,继续忽略 Python 编译产生的.pyc
、.pyo
、dist
等文件或目录:
# Python:
*.py[cod]
*.so
*.egg
*.egg-info
dist
build
加上你自己定义的文件,最终得到一个完整的.gitignore
文件,内容如下:
# Windows:
Thumbs.db
ehthumbs.db
Desktop.ini
# Python:
*.py[cod]
*.so
*.egg
*.egg-info
dist
build
# My configurations:
db.ini
deploy_key_rsa
最后一步就是把.gitignore
也提交到 Git,就完成了!当然检验.gitignore
的标准是git status
命令是不是说working directory clean
。
使用 Windows 的童鞋注意了,如果你在资源管理器里新建一个.gitignore
文件,它会非常弱智地提示你必须输入文件名,但是在文本编辑器里“保存”或者“另存为”就可以把文件保存为.gitignore
了。
有些时候,你想添加一个文件到 Git,但发现添加不了,原因是这个文件被.gitignore
忽略了:
$ git add App.class
The following paths are ignored by one of your .gitignore files:
App.class
Use -f if you really want to add them.
如果你确实想添加该文件,可以用-f
强制添加到 Git:
$ git add -f App.class
或者你发现,可能是.gitignore
写得有问题,需要找出来到底哪个规则写错了,可以用git check-ignore
命令检查:
$ git check-ignore -v App.class
.gitignore:3:*.class App.class
Git 会告诉我们,.gitignore
的第 3 行规则忽略了该文件,于是我们就可以知道应该修订哪个规则。
还有些时候,当我们编写了规则排除了部分文件时:
# 排除所有.开头的隐藏文件:
.*
# 排除所有.class文件:
*.class
但是我们发现.*
这个规则把.gitignore
也排除了,并且App.class
需要被添加到版本库,但是被*.class
规则排除了。
虽然可以用git add -f
强制添加进去,但有强迫症的童鞋还是希望不要破坏.gitignore
规则,这个时候,可以添加两条例外规则:
# 排除所有.开头的隐藏文件:
.*
# 排除所有.class文件:
*.class
# 不排除.gitignore和App.class:
!.gitignore
!App.class
把指定文件排除在.gitignore
规则外的写法就是!
+文件名,所以,只需把例外文件添加进去即可。
小结
- 忽略某些文件时,需要编写
.gitignore
; .gitignore
文件本身要放到版本库里,并且可以对.gitignore
做版本管理!- [git-cheat-sheet (1).pdf](…/…/git-cheat-sheet (1).pdf)