bingoogolapple / bingoogolapple.github.io

个人主页。同时也通过 Issues 记录学习笔记
http://www.bingoogolapple.cn
86 stars 19 forks source link

Git 学习笔记 #1

Open bingoogolapple opened 10 years ago

bingoogolapple commented 10 years ago

Git工作原理

git-osx-installer

配置 git config

影响范围说明,优先级从上往下依次递增

  • --system 该计算机范围内,基本上不会用到这个
  • --global 该计算机当前登陆用户范围内(配置自己常用的用户名和邮箱,如 GitHub 的)
  • --local 当前仓库范围内(多用于在公司项目的目录里,配置公司的项目范围里的用户名和邮箱)

配置常用别名

git config --global alias.cfg "config"
git cfg --global alias.ci "commit -a -v"
git cfg --global alias.throw "reset --hard HEAD"
git cfg --global alias.throwh "reset --hard HEAD^"
git cfg --global alias.lg "log --color --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit"

配置该计算机当前登陆用户的名字和邮箱

git cfg --global user.name "bingoogolapple"
git cfg --global user.email "bingoogolapple@gmail.com"

跳转到公司项目目录下,配置公司的项目项目范围里的用户名和邮箱

git cfg --local user.name "wanghao"
git cfg --local user.email "wanghao@domain.com"

设置 Git 大小写敏感,安装完 Git 后一定要配置这个,安装完 Git 后一定要配置这个,安装完 Git 后一定要配置这个

git cfg --global core.ignorecase false

解决 git status 中文乱码

git cfg --global core.quotepath false

防止仓库较大,curl 的 postBuffer 默认值较小时 clone 失败「Unable to rewind rpc post data - try increasing http.postBuffer」

git cfg --global http.postBuffer 20480000

设定默认的编辑器

git cfg --global core.editor vim

查看当前项目的 Git 配置信息

git cfg --local -l

查看影响整个计算机的 Git 配置信息,如果当前在一个 Git 仓库的目录中,输出的配置信息的末尾就是「git cfg --local -l」输出的信息

git cfg -l

删除某项配置,例如删除用户名

git cfg --global --unset user.name

直接编辑配置信息,默认在 vim 中编辑。每个仓库的 Git 配置文件都放在「.git/config」文件中。而当前用户的 Git 配置文件放在用户主目录下的一个隐藏文件「.gitconfig」中。你也可以找到该文件用自己喜欢的编辑器来编辑

git cfg -e
bingoogolapple commented 10 years ago

HEAD索引

这只是简单的一个文件,包含了你当前指向的那个提交的SHA-1索引值。

所有的分支指针都保存在.git/refs/heads里,HEAD在.git/HEAD里,而标签保存在.git/refs/tags里 

iqegganiddeiMac:.git iqeggandroid$ cat HEAD
ref: refs/heads/master
iqegganiddeiMac:.git iqeggandroid$ cat refs/heads/master 
30f83e55adfc88f8e42b42b0ab50790d39c7f483

git工作流

初始化

git init

添加文件到版本控制中

git add 文件1 文件2

git不会自动跟踪新建或删除文件,每次添加或删除某个文件后用git add xxx或git rm xxx很麻烦,通常在添加或者删除任意多个文件之后执行下面的命令,git会自动重新扫描当前目录下改动的文件git add和rm都被这一步代替了

git add .

提交。git commit 只负责把暂存区的修改提交到当前分支

git commit -m ""

加上-a(要先-a,再写-m),让git自动跟踪修改过的文件(前提是文件已经加入了版本控制)

git commit -a -m ""

做新的版本之前查看新的版本会保存哪些修改(和执行add .之前执行diff看到的内容差不多)

git commit -av

修改最新 commit 的 message

git commit --amend

修改老旧 commit 的 message,改为 r,然后编辑 message

git rebase -i 要修改的commit的父亲commit的hash值

合并多个 commit 的 message,改为 s 或 f,然后编辑 message。「骚操作:还能修改 commit 的顺序」

git rebase -i 要修改的commit的父亲commit的hash值

查看日志。最上面是最新的提交

git log

在一行中查看日志,不会显示日期和提交者

git log --pretty=oneline

查看分支合并图

git log --graph --pretty=oneline --abbrev-commit

查看指令使用记录(能够查看所有的版本)

git reflog

扔掉当前工作区的修改(如果之前已经执行了 git add 操作,暂存区里有该文件的修改,就变成和暂存区里的一样,否则就变成和当前分支 HEAD 里的一样)

git checkout -- <file>

恢复到某个版本(--mixed(默认值):这些 commit 的和暂存的所有文件都会被放到工作区,--soft:这些 commit 的所有文件都会被放到暂存区;--hard:这些 commit 的和暂存的所有文件都会被丢掉)

git reset --mixed 版本号

扔掉当前暂存区的修改(默认加了 --mixed,只是清空了暂存区里的修改,变成和 HEAD 一样;工作区里的内容不变)

git reset HEAD [<files>]

扔掉暂存区和工作区里所有的修改(加上 --hard 后工作区和暂存区都会被清空,变成和 HEAD 一样)

git reset --hard HEAD [<files>]

回到上(多少个^^)个版本

git reset --hard HEAD^^^

回到上(n)个版本

git reset --hard HEAD~n
bingoogolapple commented 10 years ago

忽略某个已被跟踪的文件,但不会删除该文件

git rm --cached 文件

删除某个已被跟踪的文件,如果是删除整个目录需加上-rf参数

git rm 文件

查看当前状态

git status

查看已经被跟踪的文件

git ls-files

查看工作目录和 INDEX(暂存区)之间的差异(修改后,提交前 和 上一次commit或者add .后的差异)

git diff
git diff -- 文件名1 文件名2

查看 INDEX(暂存区)和 HEAD 之间的差异(add .后 和 上一次commit的差异)

git diff --staged
git diff --cached

把刚才的修改藏起来(应用场景:开发一个大的功能时,发现之前的版本有个bug,把刚才的修改隐藏起来,然后去修复bug,修复完记得提交,然后再把刚才隐藏的修改取出来)

1、文件已经被 git 跟踪,只是修改了代码(而不是新条件文件),我们
可以使用 git stash 或 git stash save "注释" 来暂存修改。

2、如果有新添加的文件,那么就需要添加 -a 参数(如,git stash -a 或 git stash save -a "注释"),
或先 git add . 然后再使用 git stash 或 git stash save "注释" 来暂存修改。

把刚才藏起来的修改取出

git stash apply stash@{0}     // 如果是取出最近的一个stash,可以省略stash@{0}

删除stash

git stash drop stash@{0}     // 如果是删除最近的一个stash,可以省略stash@{0}

清空所有stash

git stash clear

取出并删除stash

git stash pop stash@{0}     // 如果是取出并删除最近的一个stash,可以省略stash@{0}

查看所有stash

git stash list

删除未监视的文件untracked files

# 删除 untracked files
git clean -f

# 连 untracked 的目录也一起删掉
git clean -fd

# 连 gitignore 的untrack 文件/目录也一起删掉 (慎用,一般这个是用来删掉编译出来的 .o之类的文件用的)
git clean -xfd

# 在用上述 git clean 前,墙裂建议加上 -n 参数来先看看会删掉哪些文件,防止重要文件被误删
git clean -nxfd
git clean -nf
git clean -nfd
bingoogolapple commented 9 years ago

分支操作

查看本地分支列表

git branch

列出全部分支和 commit 版本

git branch -v

查看本地分支和远程分支的跟踪关联关系

git branch -vv

查看远程分支列表

git branch -a
git branch -av

添加一个新的remote远程仓库

git remote add [remote-name] [url]

显示每个远端服务器的URL

git remote -v

origin  git@github.com:bingoogolapple/learngit.git (fetch)
origin  git@github.com:bingoogolapple/learngit.git (push)
// 上面显示了可以抓取和推送的origin的地址。如果没有推送权限,就看不到push的地址。

删除一个remote

git remote rm [name]

重命名remote

git remote rename [old-name] [new-name]

修改远程仓库地址

git remote set-url origin 仓库地址

从当前分支创建分支

git branch branchname

从当前分支创建分支+切换分支

git checkout -b branchname

从当前分支的某个版本号状态新建一个分支

git checkout 43237 -b branchname

切换到branchname分支

git checkout branchname

如果远程分支有个 develop ,而本地没有,想把远程的 develop 分支迁到本地

git checkout -b develop origin/develop

删除分支,-D表示强制删除

git branch -D branchname

删除远程分支

git push origin :branchname

提交本地test分支作为远程的master分支

git push origin test:master 

提交本地test分支作为远程的test分支

git push origin test:test

git push命令用于将本地分支的更新,推送到远程主机。它的格式与git pull命令相仿

git push <远程主机名> <本地分支名>:<远程分支名>

注意,分支推送顺序的写法是<来源地>:<目的地>,所以git pull是<远程分支>:<本地分支>,而git push是<本地分支>:<远程分支>

如果省略远程分支名,则表示将本地分支推送与之存在”追踪关系”的远程分支(通常两者同名),如果该远程分支不存在,则会被新建。

将本地的master分支推送到origin主机的master分支。如果后者不存在,则会被新建。

git push origin master

如果省略本地分支名,则表示删除指定的远程分支,因为这等同于推送一个空的本地分支到远程分支。

git push origin :master
等同于
git push origin --delete master

如果当前分支与远程分支之间存在追踪关系,则本地分支和远程分支都可以省略。将当前分支推送到origin主机的对应分支

git push origin

如果当前分支只有一个追踪分支,那么主机名都可以省略。不带任何参数的git push,默认只推送当前分支

git push

如果当前分支与多个主机存在追踪关系,则可以使用-u选项指定一个默认主机,这样后面就可以不加任何参数使用git push。

将本地的master分支推送到origin主机,同时指定origin为默认主机,后面就可以不加任何参数使用git push了。

git push -u origin master

还有一种情况,就是不管是否存在对应的远程分支,将本地的所有分支都推送到远程主机,这时需要使用–all选项。

git push --all origin

如果远程主机的版本比本地版本更新,推送时Git会报错,要求先在本地做git pull合并差异,然后再推送到远程主机。这时,如果你一定要推送,可以使用–force选项。

git push --force origin

紧急修复分支。「git merge --no-ff -m "注释" branchname」 命令用于合并指定分支到当前分支

合并分支时,加上--no-ff参数就可以用普通模式合并,合并后的历史有分支,能看出来曾经做过合并,而fast forward合并就看不出来曾经做过合并。

$ git checkout -b hotfix-1.2.1 master
$ ./bump-version.sh 1.2.1
$ git commit -a -m "Bumped version number to 1.2.1"

$ git checkout master
$ git merge --no-ff -m "注释" hotfix-1.2.1
$ git tag -a 1.2.1

$ git checkout develop
$ git merge --no-ff -m "注释" hotfix-1.2.1

$ git branch -d hotfix-1.2.1

git的合并在默认情况下会采用fast-farward merge模式,将master直接指向dev分支上,添加上 --no-ff选项之后,会执行正常合并,在Master分支上生成一个新节点,这样可以明确合并的操作
合并 test2 时「git merge test2」,合并 test3 时「git merge --no-ff test3」
![image](https://user-images.githubusercontent.com/8949716/135710850-0eda0291-4159-440b-a0d1-9a7f5da51283.png)

终止 merge

git merge --abort

继续 merge

git merge --continue

只克隆指定分支

git clone -b branchname https://github.com/bingoogolapple/GitWorkflow.git

刷新远程分支列表

git fetch -p

指定本地dev分支与远程origin/dev分支的关联关系

 git branch --set-upstream-to=origin/dev dev

取消本地dev分支与远程分支的关联关系

git branch --unset-upstream dev

从本地已有仓库建一个远程仓库

# 哑协议,没有进度
git clone --bare ~/git/VSCode/git-note/.git git-note1.git   # 只包含 git-note/.git 目录里的内容
git clone ~/git/VSCode/git-note/.git git-note2.git # 包含整个 git-note 目录里的内容
# 智能协议,有进度
git clone --bare file:///Users/wanghao/git/VSCode/git-note/.git git-note3.git # 只包含 git-note/.git 目录里的内容
git clone file:///Users/wanghao/git/VSCode/git-note/.git git-note4.git # 包含整个 git-note 目录里的内容
bingoogolapple commented 9 years ago

更新数据

GitHub两步认证

ssh-keygen -t rsa -b 4096 -C "bingoogolapple@gmail.com"
将生成的公钥添加到github中
如果开启了两步验证,还需在settings/applications/generate new token
git config --global credential.helper store

Username for 'https://github.com': bingoogolapple
Password for 'https://bingoogolapple@github.com':这里的密码就是刚才生成的token

一旦远程主机的版本库有了更新(Git术语叫做commit),需要将这些更新取回本地,这时就要用到git fetch命令。将某个远程主机的更新,全部取回本地。

git fetch <远程主机名>

取回特定分支的更新。所取回的更新,在本地主机上要用”远程主机名/分支名”的形式读取。比如origin主机的master,就要用origin/master读取。

git fetch <远程主机名> <分支名>

取回远程主机的更新以后,可以在它的基础上,使用git checkout命令创建一个新的分支。在origin/master的基础上,创建一个新分支。

git checkout -b newBrach origin/master

也可以使用git merge命令或者git rebase命令,在本地分支上合并远程分支。在当前分支上,合并origin/master。

git merge origin/master
或者
git rebase origin/master

git fetch相当于是从远程获取最新版本到本地,不会自动merge。

git fetch origin master:tmp
git diff tmp 
git merge tmp

git pull相当于是从远程获取最新版本并merge到本地

git pull origin master
bingoogolapple commented 9 years ago

标签操作

列出标签

git tag

打标签

git tag -a tagname -m "注释" 9fbc3d0  // 默认标签是打在最新提交的commit上的,加上commit id可以打在指定commit上

切换到标签,与切换分支命令相同

git checkout tagname

查看标签的版本信息

git show tagname

push单个tag到服务器

git push origin tagname

推送全部尚未推送到远程的本地标签

git push origin --tags

删除本地tag

git tag -d tagname

用push, 删除远程tag

git push origin :refs/tags/tagname

获取远程tag

git fetch origin tag tagname
bingoogolapple commented 8 years ago

重写历史

合并多个commit

git rebase -i <不变动的commit的SHA-1>
需要重点注意的是相对于正常使用的 log 命令,这些提交显示的顺序是相反的

git reflog
e23b08e HEAD@{8}: commit: b2
1694e14 HEAD@{9}: commit: b1
a9104d8 HEAD@{10}: commit (initial): a

git rebase -i a9104d8
git rebase -i HEAD~2

终止 rebase

git rebase --abort

继续 rebase

git add .
git rebase --continue
bingoogolapple commented 8 years ago

解决Git的大小不敏感问题

一是设置Git大小写敏感

git config --global core.ignorecase false

二是先删除文件,再添加进去

git rm <filename>; git add <filename> ;  git commit -m "rename file"

忽略文件

你想添加一个文件到Git,但发现添加不了,原因是这个文件被.gitignore忽略了。如果你确实想添加该文件,可以用-f强制添加到Git

git add -f test.txt

你发现,可能是.gitignore写得有问题,需要找出来到底哪个规则写错了

$ git check-ignore -v App.class
.gitignore:3:*.class    App.class

// Git会告诉我们,.gitignore的第3行规则忽略了该文件,于是我们就可以知道应该修订哪个规则。

忽略、恢复已跟踪文件的改动

忽略已跟踪的文件

git update-index --assume-unchanged /path/to/file

恢复已跟踪的文件

git update-index --no-assume-unchanged /path/to/file
bingoogolapple commented 7 years ago

多帐号配置

生成 ssh 密钥

拷贝公钥到剪贴板可以用 pbcopy 命令「pbcopy < ~/.ssh/bga_rsa.pub」

在 .ssh 目录下,增加 config 配置,config 可以配置多个 git 的帐号「vim ~/.ssh/config」

#Host myhost(这里是自定义的 host 简称,以后连接远程服务器就可以用命令 ssh myhost)[注意下面有缩进]
     #User 登录用户名(如:git)
     #HostName 主机名可用ip也可以是域名(如:github.com 或者 bitbucket.org)
     #Port 服务器open-ssh端口(默认:22,默认时一般不写此行)
     #IdentityFile 证书文件路径,是指 rsa 密钥,不是公钥 pub 文件(如 ~/.ssh/id_rsa_*)
Host github.com
    User bingoogolapple
    Hostname github.com
    IdentityFile ~/.ssh/bga_rsa

Host bitbucket.org
    User bingoogolapple
    Hostname bitbucket.org
    IdentityFile ~/.ssh/bga_rsa

Host git.company.com
    User wanghao
    Hostname git.company.com
    IdentityFile ~/.ssh/company_rsa

配置用户名和邮箱

// 设置全局范围的
git config --global user.name "bingoogolapple"
git config --global user.email "bingoogolapple@gmail.com"

// 设置仓库
git config  user.name "wanghao"
git config  user.email "wanghao@company.com"
bingoogolapple commented 4 years ago
git mv foldername tempname && git mv tempname folderName
git cat-file -t hash值
git cat-file -p hash值