Git学习

Git的一些简单操作

参考:https://www.cnblogs.com/best/p/7474442.html一小时学会Git(额,我花了2天。里面90%我搞得懂,还有10%我操作出现了问题,有部分我认为不是很对?我试了半天没试成功,可能我过于菜了?)

https://www.cnblogs.com/kevingrace/p/5690241.html (Git忽略提交规则)

设置

查看设置

1.git config

2.git config --system -l #系统设置,文件在C:Program FilesGitetcgitconfig

3.git config --global -l #当前用户设置,文件在C:UsersAdministrator.gitconfig

4.git config --local -l #当前仓库设置,文件在当前仓库通过git init生成的.gitconfig

进行设置

1.git config --global user.name "zyl"#不加双引号都是可以的,之后的大部分命令都可以选择不加“ ”或者‘ ’

2.git config user.name wyjz #不加--global就说明是只在当前仓库设置,--globla实在当前用户设置全局,也可以选择加--system

取消设置

1.git config --global --unset user.name

2.或者手动删除,其实很多命令的效果生成的文件是较简单的结果,都可以手动操作,什么创建文件,写值之类的

常用操作

常用指令

#cd:改变目录
cd #直接进入默认文件夹(一般是Home)
cd ~ #回Home(当前用户所在文件夹)
cd .. #回退到上一个目录
cd F:zyl #进入到符盘的zyl文件夹中
#
pwd #显示当前所在的目录路径
#列出当前文件夹的文件(不包括子目录)
ls #简单的列出当前文件夹下的所有文件名
ll #详细,有创建时间等
#创建文件
touch index.js #在当前文件夹中创建index.js文件
#删除文件
rm index.js #删除index.js文件
rm -r zyl #删除zyl文件夹
#创建文件夹
mkdir zyl #新建zyl文件夹
#移动文件
mv zyl zyl1 #zyl1在当前文件夹下不存在,就相当于重命名,把zyl文件夹renamezyl1
mv zyl1 project2 #project2文件夹存在,把zyl1放入project2文件夹中(project2和zyl1都在当前目录中)
#
reset #重新初始化终端/清屏
clear #清屏
history #查看历史命令
history > mylog.txt #将历史命令导出到mylog.txt文件中

文件操作

echo "123123" > a.txt #有a.txt就直接覆盖,里面将只存在123123,没有a.txt就创建a.txt
echo 123123>>a.txt #往a.txt的末尾处不换行追加123123,(除了开头的指令,后面可以不写引号和空格,大部分都可以这样)
cat a.txt #输出a.txt的内容
#git自带的vim操作
vim a #进入一个临时的a文件的界面,开始操作
i 输入 Esc :wq
#按i可以开始输入,要退出保存时先按Esc,然后:wq保存退出
:w#保存  :q#退出	:q!#不保存退出

查看状态

git status #查看所有文件状态
git status [文件名] #查看指定文件状态
git diff #显示工作区中的文件和暂存区文件的差异
git diff --cached #显示暂存区的文件和之前提交过的文件的差异
git diff HEAD [commit id] #不太确定:比较该次提交和指定的commit id提交的差异
git log #查看往期所有提交的信息,例如commit id,提交者,日期,备注,版本号等

本地仓库操作

基本操作

git init #初始化创建一个.git文件,使该文件夹开始被git管理
git add a.txt #添加a.txt文件到暂存区
git add . #添加所有文件到暂存区
git rm --cached a.txt #从暂存区移除a.txt
git rm --cached -r . #从暂存区移除所有文件
git checkout [文件名] #用暂存区的文件覆盖本地仓库的文件,例:存在a,b 暂存区有a没有b,那么只有a会被覆盖,b无反应          提交后,暂存区的文件不会消失,因为commit后这个checkout还有效
git commit -m '备注' #将所有暂存区的文件提交
git commit -a -m #效果:将所有(前提)被git管理的文件(即add过的),(结果)跳过add步骤,直接提交
git clean -df #移除所有未跟踪的文件(即删除文件夹中所有未git add的文件)
git reset --hard HEAD^ #放弃改动,回到上一次提交的结果(工作区会被覆盖成上一次提交结果,并且git log消失,只保留指定回到的提交的之前(>=)的所有commit log)凡是出现HEAD^的地方都可以选择用HEAD~n,或者HEAD [commit id]来取代,都一个效果
#想取消上一步git reset --hard HEAD^造成的回退
1.git reflog #查看仓库中所有的分支的所有更新记录,包括已经撤销的更新(因为此时git log已经消失了中间的)
2.git reset --hard HEAD@{7}或者git reset --hard e0e79d7
#--hard:撤销并删除相应的更新
#--soft:撤销相应的更新,把这些更新的内容放到Stage中(我不太懂)

#总之,我是这么理解的
#当觉得之前的提交更好的时候,通过git log和git reset --hard HEAD^来回到上一次提交
#而之后又觉得不行,想回到原来,就通过git reflog和git reset --hard --HEAD@{n}
#什么--soft啥的就别管了,应该也用不上
# 使用一次新的commit,替代上一次提交
# 如果代码没有任何新变化,则用来改写上一次commit的提交信息
git commit --amend -m [message]

# 重做上一次commit,并包括指定文件的新变化
git commit --amend [file1] [file2] ...

文件查看

git ls-files #默认查看所有缓存的文件
git ls-files -o #查看未被跟踪的文件
git ls-files --modified #查看被修改的文件

文件删除

git rm a.txt #删除a.txt,(rm是操作系统,而git rm是操作git,也就是没有被git管理的文件可以通过rm删除但是不能被git rm删除)
git rm -f a.txt #强制删除a.txt
git checkout -- a.txt #撤销删除a.txt(--后面有空格),撤销后,(嗯~ o(* ̄▽ ̄*)o不太懂欸)(应该是在commit之后删除了文件就可以从local repo恢复,但是有时候使用这个命令又说匹配不到文件)

总结:

git checkout -- [file] #下图说明:把commit中的(即Local Repo)文件覆盖工作区的文件(但是:实际上是用暂存区的文件覆盖工作区的相应的文件)
git reset --hard HEAD^ #用上一次的提交覆盖工作区,但是未被git管理的文件是不会被动的
#未被管理的意思:和.git在同一目录下,但是没有git add过
git reflog #查看历史commit之后
git reset --hard HEAD@{n} #用历史的commit覆盖工作区,不会对未被git管理的文件动手,该说效果和git reset --hard HEAD^/HEAD~n/HEAD commit-id 相同呢还是相反?
git rm --cached . #把指定的文件从暂存区移除
git checkout [文件名] #用暂存区的文件覆盖工作区,不会对未被git管理的文件动手,和第一个git checkout -- [file]似乎没有区别?唯一我看的见的区别是:git checkout a.txt会告诉你类似“update 1 path from the index”的提示,而git checkout -- a.txt 就没有什么提示了
git commit --amend -m [message] #用来改写上一次的提交,(不是新提交,只是单纯的改变)
git clean -df #清除未被git管理的当前目录的文件
除了git init,git add .,git commit -m [message],git commit -a -m [message],就上面几个挺好用?

上图备注:git checkout -- file 应该是从暂存区的操作而不是Local Repo,

git reset --soft file,git reset HEAD file 我不太懂,试了之后也没看见什么结果

分支

概念:在什么时候创建的分支,该分支拥有的东西和创建时的状态一模一样

注意:下方出现的origin指的是某一个远程,说明:git remote add origin [git远程仓库地址] #这里用到的origin是给远程仓库取了一个别名,它可以是任意值的。

git branch #列出本地分支
git branch -a #列出所有分支,本地和远程
git branch -r #列出所有远程分支
git branch [branch-name] #新建一个分支,但停留在原来的分支
git checkout [branch-name] #进入一个分支
git checkout -b [branch-name] #新建一个分支,并且进入改分支
git branch [branch-name] [commit-id] #新建一个分支指向某个提交
git merge [branch] #合并指定分支到当前分支
git cherry-pick [commit-id] #合并某个提交到当前分支
git branch -d [branch-name] #删除指定分支
git push origin --delete [branch-name] #删除远程分支
git branch -dr [remote/branch] #删除远程分支,例:git branch -dr origin/test1

冲突:Git用<<<<<<<,=======,>>>>>>>标记出不同分支的内容,其中<<<<<<< HEAD是指主分支(也就是当前分支)修改的内容,>>>>>>> cc389e1... fourth是指被合并的修改的内容,它们之间用=======分割。

远程仓库

git config --local -l #查看当前仓库的设置,可以看到远程仓库的一些信息
git remote add [别名/短的名字] url #给远程仓库取一个方便调用的名字,例:git remote add origin 	  git@github.com:xxx/xxx.git
git fetch [remote] #下载远程仓库的所有变动,默认下载后的分支是FETCH_HEAD
git branch +Table #git branch 后多按几次Table键,可以看到些分支提示,其中就有FETCH_HEAD
git remote -v #显示所有远程仓库
git remote show [remote] 显示某个远程仓库的信息
git fetch origin master #取回origin主机的master分支,一般用 远程主机名/分支名 的形式读取,例如origin/master
git fetch origin branch1:local_branch1 #使用origin这个远程仓库的branch1分支在本地创建local_branch1分支 (看情况,如果local_branch1本地存在,可能会合并可能会拒绝rejected)
git remote rename [oldname] [newname] #将远地仓库的别名修改,例:git remote rename origin origin_new
git pull [remote] [branch] #取回远程仓库的某个分支与当前本地的分支合并
git push [remote] [branch] #上传本地当前分支到远程仓库的某个分支
git clone url #将某个远程仓库克隆到本地,这个时候就不能用别名了
git remote rm [别名] #删除某个远程仓库,要求是别名,不能直接写url
git merge origin/master 或者 git rebase origin/master #在本地分支合并远程origin的master分支
git pull <远程主机名> <远程分支名>:<本地分支名>
 #取回origin的master分支与本地的test1分支合并,例:git pull origin master:test1,写成git pull origin master即是取回origin的master分支与本地仓库的当前分支合并
#git pull origin master等于git fetch origin + git merge origin/master
git push <远程主机名> <本地分支名>:<远程分支名>
# 分支推送的顺序写法是<来源地>:<目的地>,所以git pull是<远程分支>:<本地分支>,而git push是<本地分支>:<远程分支>
#创建远程分支:可以使用git push origin [本地分支]:[远程不存在的分支名],这样就创建了一个远程分支
git push --all origin #将所有本地分支推送到origin远程仓库
git push origin --tags #git push不会推送标签,需要使用--tags选项(这个我没有试过欸,不清楚)

概念知识

说明:以下只是我个人的粗鄙之见,方便我自己理解。

工作区域

1.工作区:就是通过git init生成.git的文件夹后,和.git在同一目录的就是工作区。里面的文件可以被git管理也可以不被git管理。凡是不被git管理的文件,一般情况下大部分操作,像什么合并,覆盖之类的操作都影响不到它。

2.暂存区:通过git add .添加文件后,这些文件就是进入了暂存区

3.资源库:通过git commit提交后,文件数据就是到了资源库

4.远程仓库:github

文件状态

此处是直接复制过来的

  • Untracked: 未跟踪, 此文件在文件夹中, 但并没有加入到git库, 不参与版本控制. 通过git add 状态变为Staged.
  • Unmodify: 文件已经入库, 未修改, 即版本库中的文件快照内容与文件夹中完全一致. 这种类型的文件有两种去处, 如果它被修改, 而变为Modified. 如果使用git rm移出版本库, 则成为Untracked文件
  • Modified: 文件已修改, 仅仅是修改, 并没有进行其他的操作. 这个文件也有两个去处, 通过git add可进入暂存staged状态, 使用git checkout 则丢弃修改过, 返回到unmodify状态, 这个git checkout即从库中取出文件, 覆盖当前修改
  • Staged: 暂存状态. 执行git commit则将修改同步到库中, 这时库中的文件和本地文件又变为一致, 文件为Unmodify状态. 执行git reset HEAD filename取消暂存, 文件状态为Modified

忽略提交

忽略规则

忽略提交有好几种方式,我只搞一种——仓库下创建.gitignore文件

以下来自复制

.gitignore忽略规则的匹配语法 在 .gitignore 文件中,每一行的忽略规则的语法如下: 1)空格不匹配任意文件,可作为分隔符,可用反斜杠转义 2)以“”开头的行都会被 Git 忽略。即#开头的文件标识注释,可以使用反斜杠进行转义。 3)可以使用标准的glob模式匹配。所谓的glob模式是指shell所使用的简化了的正则表达式。 4)以斜杠"/"开头表示目录;"/"结束的模式只匹配文件夹以及在该文件夹路径下的内容,但是不匹配该文件;"/"开始的模式匹配项目根目录;如果一个模式不包含斜杠,则它匹配相对于当前 .gitignore 文件路径的内容,如果该模式不在 .gitignore 文件中,则相对于项目根目录。(备注:这句话我不是很懂,具体还是看原作者博客及其举例) 5)以星号"*"通配多个字符,即匹配多个任意字符;使用两个星号"**" 表示匹配任意中间目录,比如a/**/z可以匹配 a/z, a/b/z 或 a/b/c/z等。 6)以问号"?"通配单个字符,即匹配一个任意字符; 7)以方括号"[]"包含单个字符的匹配列表,即匹配任何一个列在方括号中的字符。比如[abc]表示要么匹配一个a,要么匹配一个b,要么匹配一个c;如果在方括号中使用短划线分隔两个字符,表示所有在这两个字符范围内的都可以匹配。比如[0-9]表示匹配所有0到9的数字,[a-z]表示匹配任意的小写字母)。 8)以叹号"!"表示不忽略(跟踪)匹配到的文件或目录,即要忽略指定模式以外的文件或目录,可以在模式前加上惊叹号(!)取反。需要特别注意的是:如果文件的父目录已经被前面的规则排除掉了,那么对这个文件用"!"规则是不起作用的。也就是说"!"开头的模式表示否定,该文件将会再次被包含,如果排除了该文件的父级目录,则使用"!"也不会再次被包含。可以使用反斜杠进行转义。

需要谨记:git对于.ignore配置文件是按行从上到下进行规则匹配的,意味着如果前面的规则匹配的范围更大,则后面的规则将不会生效;

#               表示此为注释,将被Git忽略
*.a             表示忽略所有 .a 结尾的文件
!lib.a          表示但lib.a除外
/TODO           表示仅仅忽略项目根目录下的 TODO 文件,不包括 subdir/TODO
build/          表示忽略 build/目录下的所有文件,过滤整个build文件夹;
doc/*.txt       表示会忽略doc/notes.txt但不包括 doc/server/arch.txt
 
bin/:           表示忽略当前路径下的bin文件夹,该文件夹下的所有内容都会被忽略,不忽略 bin 文件
/bin:           表示忽略根目录下的bin文件
/*.c:           表示忽略cat.c,不忽略 build/cat.c
debug/*.obj:    表示忽略debug/io.obj,不忽略 debug/common/io.obj和tools/debug/io.obj
**/foo:         表示忽略/foo,a/foo,a/b/foo等
a/**/b:         表示忽略a/b, a/x/b,a/x/y/b等
!/bin/run.sh    表示不忽略bin目录下的run.sh文件
*.log:          表示忽略所有 .log 文件
config.php:     表示忽略当前路径的 config.php 文件
 
/mtk/           表示过滤整个文件夹
*.zip           表示过滤所有.zip文件
/mtk/do.c       表示过滤某个具体文件
 
被过滤掉的文件就不会出现在git仓库中(gitlab或github)了,当然本地库中还有,只是push的时候不会上传。
 
需要注意的是,gitignore还可以指定要将哪些文件添加到版本管理中,如下:
!*.zip
!/mtk/one.txt
 
唯一的区别就是规则开头多了一个感叹号,Git会将满足这类规则的文件添加到版本管理中。为什么要有两种规则呢?
想象一个场景:假如我们只需要管理/mtk/目录中的one.txt文件,这个目录中的其他文件都不需要管理,那么.gitignore规则应写为::
/mtk/*
!/mtk/one.txt
 
假设我们只有过滤规则,而没有添加规则,那么我们就需要把/mtk/目录下除了one.txt以外的所有文件都写出来!
注意上面的/mtk/*不能写为/mtk/,否则父目录被前面的规则排除掉了,one.txt文件虽然加了!过滤规则,也不会生效!
 
----------------------------------------------------------------------------------
还有一些规则如下:
fd1/*
说明:忽略目录 fd1 下的全部内容;注意,不管是根目录下的 /fd1/ 目录,还是某个子目录 /child/fd1/ 目录,都会被忽略;
 
/fd1/*
说明:忽略根目录下的 /fd1/ 目录的全部内容;
 
/*
!.gitignore
!/fw/ 
/fw/*
!/fw/bin/
!/fw/sf/
说明:忽略全部内容,但是不忽略 .gitignore 文件、根目录下的 /fw/bin/ 和 /fw/sf/ 目录;注意要先对bin/的父目录使用!规则,使其不被排除。

注意事项

当使用.gitignore不能生效(确保没有写错),应该是暂存区已经存在应该被忽略的文件导致忽略规则无法生效。

可以使用 git rm --cached -r .来清空暂存区的所有文件再add 和commit以及上传远程仓库。

上传远程仓库是直接使用本地的分支覆盖远程分支的,这样远程仓库的未忽略文件也没有了。

当不想某个文件被忽略时却被忽略了,使用 git check-ignore -v [文件名] 来看看该文件被哪个规则匹配了。

Git的缩略字母

A: 工作区新增的文件.

C: 文件的一个新拷贝.

D: 你本地删除的文件,服务器上还在。

M: 文件的内容或者mode被修改。

R: 文件名被修改了。

T: 文件的类型被修改了。

U: 文件没有被合并,需要完成合并才能进行提交。

X: 未知状态。

原文地址:https://www.cnblogs.com/woyujiezhen/p/12662911.html