Git在push时需要使用到user.name和user.email,一般通过命令来进行配置或修改。
1 2 3 4 5 6 7 8 9 10 11 | //查看user.name git config user.name //查看user.email git config user.email //配置user.name git config --global user.name "your user name" //配置user.email git config --global user.email "your user email" |
---|
这里需要注意的是,配置命令只能用于初次配置user.name/email,如果不小心配置错误,或者重复配置,不可以通过重复执行以上命令来修改user.name/email,否则可能或报错说无法重复配置,或者导致一个key配置了多个value。
如果想要修改已经配置过的user.name或email,有两种方式,一种是通过命令来修改;一种是直接修改.gitconfig文件。
//修改user.name
git config --global --replace-all user.name "your user name"
//修改user.email
git config --global --replace-all user.email"your user email"
C:\Users\{user}\.gitconfig
,直接修改里边的name或者email,如果有重复的name或email,可以将其删掉,只剩下一个就好。.gitignore
文件的作用.gitignore
文件用来忽略被指定的文件或文件夹的改动,被记录在.gitignore
文件里的文件或文件夹,是无法被git跟踪到的,换句话说,被忽略的文件是不会被放入到远程仓库里的。
也就是说,如果文件已经存在于远程仓库中,是无法通过.gitignore
文件来忽略的。
.gitignore
文件存放于git仓库的根目录下。
.gitignore
文件的语法#
表示注释,如下:
1 | # Here is comment. |
---|
直接写入文件或文件夹名即可,指定文件夹里的所有文件也会一起被忽略,如下:
1 2 3 4 5 6 7 8 | # ignore target folder target/ # ignore Eclipse files .settings/ build/ .classpath .project |
---|
!
表示不忽略指定的文件,如下:
1 2 | # don't ignore src folder !src/ |
---|
通过!
可以实现更加有意思的用法,如下:
1 2 3 | # ignore scaffolds folder, but don't ignore draft.md under scaffolds folder. scaffolds/* !scaffolds/draft.md |
---|
**注意:这里必须在文件夹后面加上/*
,否则是无法实现想要的效果的。并且被忽略的文件和想要不忽略的文件必须是同一路径,否则无法生效。**如下的写法就是不能生效的:
1 2 3 | # ignore scaffolds folder, but don't ignore draft.md under scaffolds folder. scaffolds/* !scaffolds/test/draft.md |
---|
想要生效就要改成同一目录:
1 2 3 | # ignore scaffolds folder, but don't ignore draft.md under scaffolds folder. scaffolds/test/* !scaffolds/test/draft.md |
---|
可以使用通配符及其他符号来指定复杂条件的文件,如下:
1 2 3 4 | *.log day_1?.txt hello[0-9].txt hi[^0-9].txt |
---|
*
表示匹配任意字符;?
表示匹配一个字符;[]
表示匹配中括号内的单个字符:-
来表示连贯的字符,比如0-9
,a-z
,A-Z
等,[0-9]
表示匹配从0到9的单个字符。^
来表示除外,比如[^0-9]
表示除0到9之外的单个字符。如果某个文件已经存在于远程仓库了,也就是说某个文件已经被版本控制了,如果将该文件添加到.gitignore
中,是无法生效的。因为.gitignore
是用来控制尚未被纳入版本控制的文件,如果文件已经存在于远程库中,自然也就无法生效了。
于是就此衍生了一个问题:.gitignore
怎么忽略已经被版本控制的文件?
直接在远程库里将想要忽略的文件删除掉,再将该文件写入.gitignore
中即可。
这种做法的前提是,你确定该文件是允许从远程库删除掉的,然而有些时候,这种做法是不可能的。要么没权限去远程库删掉该文件,要么该文件是必须的。
使用命令git rm --cached filename
,然后将该文件写入.gitignore
中即可。
该命令表示从git仓库中将文件移除,不再进行版本控制,但保留工作区的该文件。
需要注意的是,该命令其实和方法一差不多。git rm
表示移除某个文件,--cached
表示从暂存区中移除,如果不加该参数就是直接从工作区移除了。
工作区就是指的Working Tree,暂存区就是指的Stage。工作区就是我们的磁盘,被版本控制的文件都存放于工作区。如果改动了某个文件,首先要将该文件添加到暂存区(Stage),然后再提交(commit)到本地仓库,最后才推送(push)到远程库。
git rm --cached filename
并不会从物理上删除文件,只是从暂存区中将文件删除。由于该文件原本已经被版本控制了,使用了该命令后,虽然保留了工作区的该文件,但是却会在暂存区中生成一个删除了该文件的记录,如果此时进行commit,就会把版本库里的该文件给删掉了,如果push到远程库,也会被删掉。最终还是走的方法一的路子。
git rm --cached filename
的补充看到有篇文章举例很详细,如下:
git rm —cached 1.txt
:git rm —cached 1.txt
:git rm —cached 1.txt
:git rm —cached 1.txt
会报错,不能执行操作。我在本地有个代码仓库local-A,本地仓库local-A已经和一个远程仓库remote-A关联了。
接着我又在GitHub上新建了一个仓库remote-B,我希望将本地仓库local-A的本地dev分支push到这个新建的远程库remote-B。我的想法是这样的:
接着当我做到第三步的时候,发现报错如下:
1 | Merge: refusing to merge unrelated histories |
---|
看到报错,我又重新操作了一遍,依然是同样的错误。记得以前我也做过类似的操作,但是却没有现在的问题,百度了下,发现可能是git升级之后造成的。
因为两个仓库是不同的项目(本地仓库已经跟踪了另外一个远程库了),git默认不允许不相干的项目进行push等操作。如果想要进行这些操作,就需要加入--allow-unrelated-histories
参数才可以合并两个不同的项目:
1 | git merge --squash dev --allow-unrelated-histories |
---|
这句命令表示将dev
分支合并到当前分支,这里的两个本地分支各自追踪不同的远程库,需要加入--allow-unrelated-histories
参数才能够完成合并操作而不报错,至于--squash
参数是为了压缩dev
分支原本的commit历史,可以将原本所有的commit历史合成一个commit,以避免当前分支在合并之后掺入了其他项目的commit历史。
这个问题由不同平台的换行符不同所造成:
\r
(return)。LF是换行,LineFeed,即\n
(newline)。影响:
^M
符号。解决方法:
为了避免git管理的项目中出现混合的换行符,通常会将项目的换行符设置为LF
。
对于Windows平台,git的客户端默认设置为core.autocrlf=true
。在提交文件时,会自动将换行符转换为LF
,在检出文件时则自动转为CRLF
。
1 | git config --global core.autocrlf true |
---|
对于Mac和Linux平台,可以将配置设置为input
。这样在提交文件时会转为LF
,检出时则不转换。
1 | git config --global core.autocrlf input |
---|
如果只使用Windows平台进行开发并运行项目,可以设置为false
,来取消git自动转换换行符的功能。
1 | git config --global core.autocrlf false |
---|
还可以配置core.safecrlf
来改变git对于换行符的检查行为:
1 2 3 4 5 6 7 8 | #拒绝提交包含混合换行符的文件 git config --global core.safecrlf true #允许提交包含混合换行符的文件 git config --global core.safecrlf false #提交包含混合换行符的文件时给出警告 git config --global core.safecrlf warn |
---|
可以通过以下命令来查询Git的配置:
1 2 3 4 5 | // 查询配置 git config -l // 查询全局配置 git config -l --global |
---|
可以在git bash
里用git log
命令来统计,部分参数说明如下:
1 2 3 4 5 6 7 8 9 10 11 12 | --author 指定作者 --stat 显示每次更新的文件修改统计信息,会列出具体文件列表 --shortstat 统计每个commit 的文件修改行数,包括增加,删除,但不列出文件列表 --numstat 统计每个commit 的文件修改行数,包括增加,删除,并列出文件列表 --pretty 使用其他格式显示历史提交信息 --pretty=tformat 可以定制要显示的记录格式 --since, --after 仅显示指定时间之后的提交 --until, --before 仅显示指定时间之前的提交 -w 显示字数 -c 显示Bytes数 -l 显示行数 |
---|
统计某段时间内的提交:
1 | git log --since ==2021-09-01 --until=2021-10-05 | wc -l |
---|
统计当前用户的代码提交量,包括增加、删除:
1 | git log --author="$(git config --get user.name)" --pretty=tformat: --numstat | gawk '{ add += $1 ; subs += $2 ; loc += $1 - $2 } END { printf "added lines: %s removed lines : %s total lines: %s\n",add,subs,loc }' |
---|
统计仓库排名前五的提交:
1 2 3 4 | git log --pretty='%aN' | sort | uniq -c | sort -k1 -n -r | head -n 5 --按照邮箱来统计排名前五的提交(邮箱名不同,但是用户名可以相同) git log --pretty=format:%ae | gawk -- '{ ++c[$0]; } END { for(cc in c) printf "%5d %s\n",c[cc],cc; }' | sort -u -n -r | head -n 5 |
---|
贡献者统计:
1 | git log --pretty='%aN' | sort -u | wc -l |
---|
提交数统计:
1 | git log --oneline | wc -l |
---|
添加或修改的代码行数:
1 | git log --stat|perl -ne 'END { print $c } $c += $1 if /(\d+) insertions/;' |
---|
如果在cmd窗口中输入git reset --hard HEAD^
会显示more?
,原因是^
在cmd窗口中代表换行符,因此这里会通过回显more?
来询问你是否还需要输入更多命令。
解决方法有如下几种:
git reset --hard "HEAD^"
^
进行转义:git reset --hard HEAD^^
~
:git reset --hard HEAD~
或者 git reset --hard HEAD~1
~
后面的数字表示回退几次提交,默认是一次。
如果使用git bash
或者powershell
则不会出现该问题。