.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.alib.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.txtnew_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_branchmaster是没有合并的两个分区,如果想在没合并的前提下删除new_branch,可以使用参数-D进行强制删除,那我们使用-D强制删除试试:

$ git branch -D new_branch
Deleted branch new_branch (was 5e0c211).
$ git branch
* master

发现new_branch已经删除了,并且先前在new_branch中提交test1.txtgit log也已经删除了,我们再创建new_branchtest1.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对象链:一条工作记路线

分支1.png

Git每次提交都记录着上一次的提交ID,这样就形成了一条完整的时间线,每一次的Parent都指向上一次的提交ID
分支2.png

  • HEAD指向的是当前分支
  • master指向提交

HEAD并不指向当前提交,而是指向当前分支,而master才是指向当前提交,所以HEAD指向master

分支3.png

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了,就如图所示的样子了

分支4.png

此图显示的状态是,我们在dev分支上,又做了一次提交,就像我们在dev上面修改创建了一个文件,做了一次提交,所以我们如果在master上面使用git branch -d命令,会显示两个分支没有合并,只能使用git branch -D强制删除

分支5.png

我们可以使用git log对比一下masterdevlog:

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

可以发现masterlogdevlog已经相同了

两个分支不互通的情况

假如我们在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试试:

可以直接在mastervim 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

会发现masterdev的更新记录更快一步,这一步是: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试试在devgit 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给合并过来了,这是为什么了?

合并讲解

这是最先我们devmaster都不一样的时候的样子,两个分支都有修改

合并1.png

这是我们在master进行了git add test.txt后的样子,相当于master向前跳了一个版本,但这个版本是跟一起那个master一样的,所以有这样的显示:Merge branch 'dev' into master,这样master就比dev更快一步了,并且两个分支建立了联系

合并2.png

我们再在dev中将master合并过来,这样使用git merge master或者在master中使用git merage dev就不会出现报错了,这样两个分支就完成合并了

合并3.png

参考资料

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]

Last modification:December 5th, 2020 at 12:24 pm