.gitignore与分支
.gitignore
一般来说每个Git项目中都需要一个.gitignore
文件,这个文件的作用就是告诉Git哪些文件不需要添加到版本管理中,比如Android项目中的iml
文件及build
目录下编译生成的文件,项目中经常会有很多临时文件, 如临时的编译中间文件, 通常这些文件不需要加入到版本控制中. 如何在提交的时候跳过这些文件? 一种办法是很繁琐的在 git add 的时候手动添加需要加入版本控制的文件, 这种方法不仅繁琐也很容易犯错.还有一个办法就是使用 gitignore 文件
哪些文件需要放入到.gitignore
里
通常, 能够通过其他文件自动生成的都不需要放入版本控制, 如编译产生的临时文件.
还有, 操作系统会创建自动创建一些文件, 如缩略图, 这些也不需要放入版本控制
最后, 某些比较敏感的文件, 比如包含数据库连接密码的配置文件也不要放到公共 git 仓库里
不过, 并不是一定如此, 还是得具体问题具体分析
总结
- gitignore 是用来过滤不想加入版本控制的文件用的
- 可以找到很多现成的 gitignore 文件
- 你应该尽早编写gitignore并及时提交
具体操作讲解
创建一个properties
文件
$ echo "my project configuration" > settings.properties
查看状态
$ git status
On branch master
Untracked files:
(use "git add <file>..." to include in what will be committed)
settings.properties
nothing added to commit but untracked files present (use "git add" to track)
会显示这个properties
文件一直处于是未追踪的状态,不管你以后是否提交了txt
文件到版本库中,都会一直显示未追踪,但按理来说,我们不能将项目有关的配置文件提交到Git的版本库中,这时候就需要properties
放进版本库
创建.gitignore
$ vim .gitignore
查看文件以及git status
$ ls -al
total 59
drwxr-xr-x 1 A 197609 0 11月 15 20:34 ./
drwxr-xr-x 1 A 197609 0 11月 15 10:20 ../
drwxr-xr-x 1 A 197609 0 11月 15 20:29 .git/
-rw-r--r-- 1 A 197609 0 11月 15 20:34 .gitignore
-rw-r--r-- 1 A 197609 25 11月 15 20:29 settings.properties
-rw-r--r-- 1 A 197609 16 11月 14 17:17 test.txt
-rw-r--r-- 1 A 197609 13 11月 14 11:56 test2.txt
$ git status
On branch master
Untracked files:
(use "git add <file>..." to include in what will be committed)
.gitignore
settings.properties
nothing added to commit but untracked files present (use "git add" to track)
这时候我们再vim .gitignore
$ vim .gitignore
在.gitignore
里面加入文件名 settings.properties
$ cat .gitignore
settings.properties
我们这时候再git status
一下,就可以发现 settings.properties
不见了
$ git status
On branch master
Untracked files:
(use "git add <file>..." to include in what will be committed)
.gitignore
nothing added to commit but untracked files present (use "git add" to track)
我们提交.gitignore
到暂存区和版本库中
$ git add .gitignore
warning: LF will be replaced by CRLF in .gitignore.
The file will have its original line endings in your working directory
$ git commit -m 'add .gitignore'
[master 095b97f] add .gitignore
1 file changed, 2 insertions(+)
create mode 100644 .gitignore
查看一下
$ git status
On branch master
nothing to commit, working tree clean
$ ls -al
total 60
drwxr-xr-x 1 A 197609 0 11月 15 20:37 ./
drwxr-xr-x 1 A 197609 0 11月 15 10:20 ../
drwxr-xr-x 1 A 197609 0 11月 15 20:42 .git/
-rw-r--r-- 1 A 197609 21 11月 15 20:37 .gitignore
-rw-r--r-- 1 A 197609 25 11月 15 20:29 settings.properties
-rw-r--r-- 1 A 197609 16 11月 14 17:17 test.txt
-rw-r--r-- 1 A 197609 13 11月 14 11:56 test2.txt
可以发现,setting.properties
文件还是在的,但是被Git给忽略掉了,说明我们的项目的配置文件,无论你做任何修改,Git都会忽略掉
再试一次
创建一个a.b
文件
$ echo 'another file' > a.b
$ cat .gitignore
settings.properties
a.b
$ git add .
warning: LF will be replaced by CRLF in .gitignore.
The file will have its original line endings in your working directory
$ git commit -m 'update .gitignore'
[master df216c5] update .gitignore
1 file changed, 1 insertion(+), 1 deletion(-)
$ git status
On branch master
nothing to commit, working tree clean
忽略文件
.gitignore
文件
*.a | 忽略所有.a 结尾的文件 |
---|---|
!lib.a | 但lib.a 除外 |
/TODO | 仅仅忽略项目根目录下的TODO 文件,不包括subdir/TODO |
build/ | 忽略build/ 目录下的所有文件 |
doc/*.txt | 会忽略doc/notes.txt 但不包括doc/server/arch.txt |
例:
创建一个test3.txt
,并且查看git status
$ echo 'test3' >test3.txt
$ git status
On branch master
No commits yet
Untracked files:
(use "git add <file>..." to include in what will be committed)
.gitignore
test3.txt
nothing added to commit but untracked files present (use "git add" to track)
修改一下.gitignore
,再查看下git status
/test3.txt
$ git status
On branch master
No commits yet
Untracked files:
(use "git add <file>..." to include in what will be committed)
.gitignore
发现test3.txt
没了,但是这时候我们再创建一个mydir
目录,在mydir
里面创建一个mydirtest3.txt
, 再查看git status
$ cat mydirtest3.txt
test3
$ git status
On branch master
No commits yet
Untracked files:
(use "git add <file>..." to include in what will be committed)
.gitignore
mydir/
注意:这时候我们在Gitfile
根目录下进行git status
与在mydir
目录下进行git status
是不一样的,对比效果如下:
Gitfile
.gitignore mydir/
mydir
../.gitignore ./
如果想把
mydirtest3.txt
也忽略掉,可以在.gitignore
里面添加:/*/mydirtest3.txt
这样
mydirtest3.txt
就忽略掉了,但如果我们每层目录下都要这样写,那样就很麻烦,例如:我们在mydirtest
下面创建一个目录yourdir
,然后在里面也创建一个test3.txt
,查看一下:No commits yet Untracked files: (use "git add <file>..." to include in what will be committed) .gitignore mydir/
我们想把所有目录下的
test3.txt
都忽略掉,可以加上两个**
/**/test3.txt
这样就都忽略掉了
- build
如果我们在
.gitignore
忽略文件前面加上#
注释掉,则该忽略失效,我们想使一个目录下的所有文件都失效,可以这样:mydir/
这样
mydir
下面的所有文件就都忽略掉了
重要的分支
当我使用命令git init
初始化一个Git厂库的时候,Git给我们初始化了一个master
主分支,这时候我们如果想查看我们是在哪个分支,可以使用一个命令查看:
$ git branch
如果想创建一个新的分支,则可以在命令后面加入参数,参数就是新的分支名字,列如:
$ git branch new_branch
再使用git branch
查看,就会发现多了一个分支了:
$ git branch
* master
new_branch
注:如果我们最开始就git init
一个Git厂库,啥都没有,然后就git branch
是会报错的,那是因为你暂存区与版本库没有任何东西,所以想要创建新的分支,必须是要工作区的
在不同分支之间来回穿梭,与创建后立即进入
如果想在分支之间切换,则可以使用命令git checkout + 分支名
,例:
$ git checkout new_branch
Switched to branch 'new_branch'
checkout
后面可以跟一个参数,就可以在创建一个新的分支后立即进入,这个参数就是-b
,例:
$ git checkout -b new_branch
Switched to a new branch 'new_branch'
如果也在此分支立刻返回到先前所在的分支,也如同切换文件一样,可以跟上-
,例:当前我是在new_branch
,想回到master
$ git checkout -
Switched to branch 'master'
我们在不同的分支切换,其实就是在master
与分支之间切换,在windows
Mac
或虚拟机的图形化界面下,查看Gitfile
会发现在切换分支时,文件是都在Gitfile master
那个页面中变幻,而不会是创建了新的文件夹,我们在另外的分支中创建文件,如果没有合并分支,在master
中都是看不到的
删除分支
想要删除分支,要分为两种情况:无任何修改与已有修改
无任何修改的分支删除
如果我们创建一个分支,没有任何的修改,意思是跟master
一样,想要删除这个分支,则直接在git branch
后面加参数-d
,例如下:
$ git branch -d new_branch
Deleted branch new_branch (was df216c5).
这样new_branch
就删除掉了
已有修改操作的分支删除
我们重新创建一个new_branch
并且向里面添加一个test1.txt
,让这个文件提交到版本库中,再使用-d
参数试试:
已提交test1.txt
到new_branch
的版本库:
A@DESKTOP-6DP8MG1 MINGW64 /e/Gitfile (new_branch)
$ git commit -m 'new_branch test1.txt first'
[new_branch 5e0c211] new_branch test1.txt first
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 test1.txt
使用git log
查看,可以很清楚的看到test1.txt
是在new_branch
提交的记录:
commit 5e0c211f1c85a429cf8458eeb91a40043aaca6be (HEAD -> new_branch)
new_branch test1.txt first
我们回到master
,试图用-d
参数删除new_branch
:
$ git branch -d new_branch
error: The branch 'new_branch' is not fully merged.
If you are sure you want to delete it, run 'git branch -D new_branch'.
出现提示,提示你new_branch
跟master
是没有合并的两个分区,如果想在没合并的前提下删除new_branch
,可以使用参数-D
进行强制删除,那我们使用-D
强制删除试试:
$ git branch -D new_branch
Deleted branch new_branch (was 5e0c211).
$ git branch
* master
发现new_branch
已经删除了,并且先前在new_branch
中提交test1.txt
的git log
也已经删除了,我们再创建new_branch
与test1.txt
这时候来合并试试,合并两个版本需要使用使用git merge
这个命令,我们回到master
使用
$ git merge new_branch
Merge made by the 'recursive' strategy.
test1.txt | 0
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 test1.txt
这时候发现我们的master
中的test1.txt
已经变为了new_branch
中的test1.txt
这时候我们再调用-d
参数,看是否能删除new_branch
:
$ git branch -d new_branch
Deleted branch new_branch (was afa98a1).
A@DESKTOP-6DP8MG1 MINGW64 /e/Gitfile (master)
$ git branch
* master
我们可以使用-v
参数查看当前分支最新的一条提交信息,例如:
$ git branch -v
* master f25e8c3 Merge branch 'new_branch' into master
分支的本质
- 一个
commit
对象链:一条工作记路线
Git每次提交都记录着上一次的提交ID,这样就形成了一条完整的时间线,每一次的Parent
都指向上一次的提交ID
HEAD
指向的是当前分支master
指向提交
HEAD
并不指向当前提交,而是指向当前分支,而master
才是指向当前提交,所以HEAD
指向master
dev
的意思是指我使用git branch dev
,是在这时候创建了一个dev
分支,相当于你执行了git checkout -b dev
这条命令,创建了dev
分支并且进入了此分支,所以HEAD
是指向dev
的
而HEAD
是在哪了?HEAD
是在.git
目录下,我们现在查看一下:
$ cd .git
A@DESKTOP-6DP8MG1 MINGW64 /e/Gitfile/.git (GIT_DIR!)
$ cat HEAD
ref: refs/heads/master
可以显示当前HEAD
是指向的master
我们创建一个dev
分支,再查看一下HEAD
:
A@DESKTOP-6DP8MG1 MINGW64 /e/Gitfile (master)
$ git checkout -b dev
Switched to a new branch 'dev'
A@DESKTOP-6DP8MG1 MINGW64 /e/Gitfile (dev)
$ cd .git
A@DESKTOP-6DP8MG1 MINGW64 /e/Gitfile/.git (GIT_DIR!)
$ cat HEAD
ref: refs/heads/dev
可以看到当前HEAD
就是在dev
了,就如图所示的样子了
此图显示的状态是,我们在dev
分支上,又做了一次提交,就像我们在dev
上面修改创建了一个文件,做了一次提交,所以我们如果在master
上面使用git branch -d
命令,会显示两个分支没有合并,只能使用git branch -D
强制删除
我们可以使用git log
对比一下master
与dev
的log
:
dev
:
commit 4ca3bca9404b69f665cb950903c332821987c58d (HEAD -> dev)
Author: YQHP-YuKi <************@qq.com>
Date: Thu Nov 19 15:05:19 2020 +0800
add new line on dev
commit f25e8c3063b088c3aa1f1239891538780c167cd2 (master)
Merge: 7d9a3e0 afa98a1
Author: YQHP-YuKi <************@qq.com>
Date: Tue Nov 17 23:18:47 2020 +0800
Merge branch 'new_branch' into master
commit 7d9a3e074e8c3265e416a738543d7c5cd820c9e0
Author: YQHP-YuKi <************@qq.com>
Date: Tue Nov 17 23:17:49 2020 +0800
master
:
commit f25e8c3063b088c3aa1f1239891538780c167cd2 (HEAD -> master)
Merge: 7d9a3e0 afa98a1
Author: YQHP-YuKi <************@qq.com>
Date: Tue Nov 17 23:18:47 2020 +0800
Merge branch 'new_branch' into master
commit 7d9a3e074e8c3265e416a738543d7c5cd820c9e0
Author: YQHP-YuKi <***********@qq.com>
Date: Tue Nov 17 23:17:49 2020 +0800
deledt .gitignore
commit afa98a1419abcd04ffdbd95d2398035e40f3b540
Author: YQHP-YuKi <************@qq.com>
Date: Tue Nov 17 23:11:40 2020 +0800
new_branch test1.txt second
我们可以发现dev
的第二条提交信息是master
的第一条提交信息,dev
第3条提交信息是master
第2条提交信息
然后我们在master
上面执行git merge
$ git merge dev
Updating f25e8c3..4ca3bca
Fast-forward
test.txt | 1 +
1 file changed, 1 insertion(+)
显示更新了f25e8c3
,我们再在master
上面git log
一下:
commit 4ca3bca9404b69f665cb950903c332821987c58d (HEAD -> master, dev)
Author: YQHP-YuKi <***********@qq.com>
Date: Thu Nov 19 15:05:19 2020 +0800
add new line on dev
commit f25e8c3063b088c3aa1f1239891538780c167cd2
Merge: 7d9a3e0 afa98a1
Author: YQHP-YuKi <***********@qq.com>
Date: Tue Nov 17 23:18:47 2020 +0800
Merge branch 'new_branch' into master
commit 7d9a3e074e8c3265e416a738543d7c5cd820c9e0
Author: YQHP-YuKi <***********@qq.com>
Date: Tue Nov 17 23:17:49 2020 +0800
deledt .gitignore
可以发现master
的log
与dev
的log
已经相同了
两个分支不互通的情况
假如我们在master
上面做了修改,也在dev
上面做了修改,会发生什么了?
我们先修改master
:
A@DESKTOP-6DP8MG1 MINGW64 /e/Gitfile (master)
$ vim test.txt
A@DESKTOP-6DP8MG1 MINGW64 /e/Gitfile (master)
$ git add .
A@DESKTOP-6DP8MG1 MINGW64 /e/Gitfile (master)
$ git commit -m "this is master in test.txt"
[master 6162e11] this is master in test.txt
1 file changed, 1 insertion(+)
A@DESKTOP-6DP8MG1 MINGW64 /e/Gitfile (master)
$ git status
On branch master
nothing to commit, working tree clean
再在dev
上面修改:
$ git checkout dev
Switched to branch 'dev'
A@DESKTOP-6DP8MG1 MINGW64 /e/Gitfile (dev)
$ vim test.txt
A@DESKTOP-6DP8MG1 MINGW64 /e/Gitfile (dev)
$ git add .
A@DESKTOP-6DP8MG1 MINGW64 /e/Gitfile (dev)
$ git commit -m 'this is dev in test.txt'
[dev 0a3a478] this is dev in test.txt
1 file changed, 1 insertion(+)
我们回到master
,尝试使用git merge
试试:
$ git checkout master
Switched to branch 'master'
A@DESKTOP-6DP8MG1 MINGW64 /e/Gitfile (master)
$ git merge dev
Auto-merging test.txt
CONFLICT (content): Merge conflict in test.txt
Automatic merge failed; fix conflicts and then commit the result.
报错了,显示了在合并test.txt
时,因为两个文件不符合,出现了报错
我们查看一下test.txt
$ cat test.txt
I am YQHP-YuKi
hello everyone
<<<<<<< HEAD
this is master
=======
this is dev
>>>>>>> dev
因为HEAD
代表的是当前分支,我们当前是在master
,所以master
的是this is master
,dev
的是this is dev
,我们删除dev
中的this is dev
试试:
可以直接在master
中vim test.txt
,然后按dd
删除:
$ cat test.txt
I am YQHP-YuKi
hello everyone
this is master
查看一下状态:
$ git status
On branch master
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: test.txt
no changes added to commit (use "git add" and/or "git commit -a")
这时候我们使用git add
这条命令,但这时的git add
并非以前的git add
意思,这时候的意思是告诉git
我已经解决了这个冲突
$ git add test.txt
A@DESKTOP-6DP8MG1 MINGW64 /e/Gitfile (master|MERGING)
$ git status
On branch master
All conflicts fixed but you are still merging.
(use "git commit" to conclude merge)
我们使用git commit
可以完成mearing
:
$ git commit
[master a41fd9e] Merge branch 'dev' into master
A@DESKTOP-6DP8MG1 MINGW64 /e/Gitfile (master)
$ git status
On branch master
nothing to commit, working tree clean
保存退出文档即可
查看一下test.txt
:
$ cat test.txt
I am YQHP-YuKi
hello everyone
this is master
已经变为了master
的了,我们git log
一下:
master
:
commit a41fd9e529c9a9e0b746745beae653b6736dac46 (HEAD -> master)
Merge: 6162e11 0a3a478
Author: YQHP-YuKi <***********@qq.com>
Date: Thu Nov 19 15:42:10 2020 +0800
Merge branch 'dev' into master
commit 0a3a478dc18d6b39a53e7ad3cbbecdda0531071a (dev)
Author: YQHP-YuKi <***********@qq.com>
Date: Thu Nov 19 15:25:09 2020 +0800
this is dev in test.txt
commit 6162e11b99c56f3e2e0f8c8bce933bbaa7081f26
Author: YQHP-YuKi <***********@qq.com>
Date: Thu Nov 19 15:22:15 2020 +0800
this is master in test.txt
commit 4ca3bca9404b69f665cb950903c332821987c58d
Author: YQHP-YuKi <************@qq.com>
Date: Thu Nov 19 15:05:19 2020 +0800
dev
:
commit 0a3a478dc18d6b39a53e7ad3cbbecdda0531071a (HEAD -> dev)
Author: YQHP-YuKi <**************@qq.com>
Date: Thu Nov 19 15:25:09 2020 +0800
this is dev in test.txt
commit 4ca3bca9404b69f665cb950903c332821987c58d
Author: YQHP-YuKi <**************@qq.com>
Date: Thu Nov 19 15:05:19 2020 +0800
add new line on dev
commit f25e8c3063b088c3aa1f1239891538780c167cd2
Merge: 7d9a3e0 afa98a1
Author: YQHP-YuKi <**************@qq.com>
Date: Tue Nov 17 23:18:47 2020 +0800
Merge branch 'new_branch' into master
commit 7d9a3e074e8c3265e416a738543d7c5cd820c9e0
Author: YQHP-YuKi <***************@qq.com>
Date: Tue Nov 17 23:17:49 2020 +0800
会发现master
比dev
的更新记录更快一步,这一步是:Merge branch 'dev' into master
,但现在两边的test.txt
一样吗?查看下:
master
:
A@DESKTOP-6DP8MG1 MINGW64 /e/Gitfile (master)
$ cat test.txt
I am YQHP-YuKi
hello everyone
this is master
dev
:
A@DESKTOP-6DP8MG1 MINGW64 /e/Gitfile (dev)
$ cat test.txt
I am YQHP-YuKi
hello everyone
this is dev
发现两边仍然不一样,那我们切换到dev
试试在dev
中git merge
一下:
A@DESKTOP-6DP8MG1 MINGW64 /e/Gitfile (dev)
$ git merge master
Updating 0a3a478..a41fd9e
Fast-forward
test.txt | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
居然没有报错,并且成功的将master
给合并过来了,这是为什么了?
合并讲解
这是最先我们dev
与master
都不一样的时候的样子,两个分支都有修改
这是我们在master
进行了git add test.txt
后的样子,相当于master
向前跳了一个版本,但这个版本是跟一起那个master
一样的,所以有这样的显示:Merge branch 'dev' into master
,这样master
就比dev
更快一步了,并且两个分支建立了联系
我们再在dev
中将master
合并过来,这样使用git merge master
或者在master
中使用git merage dev
就不会出现报错了,这样两个分支就完成合并了
参考资料
B站评论区大佬博客:https://www.cnblogs.com/AhuntSun-blog/p/12745183.html
git 官方文档: https://git-scm.com/docs/gitignore
segmentfault https://segmentfault.com/a/1190000000522997
廖雪峰的博客 : [http://www.liaoxuefeng.com/wiki/0013739516305929606dd18361248578c67b8067c8c017b000/0013758404317281e54b6f5375640abbb11e67be4cd49e0000]