入门
- .git 的隐藏目录是你的本地仓库(Local Repository)
git log
查看历史git log -p
查看详细历史git log --stat
查看简要统计git show e66666/branch
查看指定commit,加文件名看指定文件git diff --staged/--cached
查看当前工作目录与暂存区的不同,可以看到即将添加到暂存区的改动内容,git diff HEAD
看到当前工作目录与上一个commit的不同- commit 的 SHA-1 校验和
commit 8cf88cf35ce40cb91488e7d9b12cf46463fedc2f
- commit 的 SHA-1 校验和
git status
- untracked files (未追踪的文件)
- 使用
git add git.txt
来开始追踪文件- 从 “Untracked files” 变成了 “Changes to be commited”,该文件变成已暂存staged,被记录到 staging area(暂存区)
git commit -m "add git.txt"
提交代码到本地仓库
- 缓存GitHub密码,在设置了SSH key后,
git config --global credential.helper wincred
git push
到远端仓库git pull
将远端仓库代码同步到本地仓库- push冲突,由于 GitHub 的远端仓库上含有本地仓库没有的内容,所以这次 push 被拒绝,解决办法:先用 pull 把远端仓库上的新内容取回到本地和本地合并,合并后的代码会自动提交,然后再把合并后的本地仓库向远端仓库推送
HEAD、master、branch
- commit 后面括号里的 HEAD -> master, origin/master, origin/HEAD ,是指向这个 commit 的引用,也可以使用SHA-1指代commit
HEAD 当前 commit 的引用
- 当前工作目录对应的commit,checkout/reset会改变当前commit
branch
- HEAD 除了可以指向 commit,还可以指向一个 branch,HEAD指向分支master,间接指向对应的commit,当
git commit
有新的提交时,HEAD会和master一起指向新的commit - master 默认的主分支,和其他分支平等,分支可以理解为初始commit到当前分支指向的commit的路径
- branch 的创建、切换和删除
- 创建 branch
git branch feature1
- 切换分支
git checkout feature1
HEAD 就会指向新建的 branch,执行git checkout -b feature1
是上述两个合并执行 - 删除分支
git branch -d feature1
,HEAD 指向的 branch 不能删除。如果要删除 HEAD 指向的 branch,需要先用 checkout 把 HEAD 指向其他分支,没有被合并到 master 过的 branch 在删除时会失败,确认删除使用git branch -D feature1
- 创建 branch
push
git push
当前master分支,把该分支上的未上传的commit,以及当前master所指向的commit引用一并上传到远端切换到feature1,执行push,
origin feature1
参数代表目标仓库和目标分支1
2git checkout feature1
git push origin feature1git config push.default current
推送到与当前分支相同的远端分支,参考git config- HEAD指向默认分支master,在
git push
时,只会上传当前分支的指向,例如push后,本地feature1指向第5个commit,push后远端feature1分支指向第5个commit,而HEAD指向不会切换到feature1的指向,默认指向master分支的commitmerge
pull
执行了fetch
拉取到本地,merge
合并远端commit和本地commit git merge branch1
把branch1分支合并到master分支,生成一个新的commit两个分支修改相同内容,造成合并冲突,可以删除冲突的内容重新合并
1
2git add git.txt
git commit也可以取消合并
git merge --abort
,回到之前的commit状态- 当HEAD领先于branch的commit,在同一路径上,merge 是空操作,不需要创建新的commit
- 当HEAD落后于目标branch的commit,在同一路径上,merge会直接将HEAD指向目标commit,这个操作即是 fast-forward 快速前移,在本地仓库中commit落后于远端代码,造成本地HEAD落后与目标commit,
git pull
就会造成fast-forward origin/master
和origin/HEAD
是对远端仓库的 master 和 HEAD 的本地镜像,在git pull
中的第一步git fetch
下载远端仓库内容时,这两个镜像引用得到了更新,origin/master
和origin/HEAD
移动到了最新的 commitFeature Branching
- 任何新的功能(feature)或 bug 修复全都新建一个 branch
- branch 写完后,合并到 master,然后删掉这个 branch
开发一个新的功能,创建新的分支
1
git checkout -b feature1
功能基本完成后,push到远端分支feature1
1
git push origin feature1
review 复审代码,通过后合并分支到master
1
2
3
4
5
6git pull
git chekcout feature1
···
git checkout master
git pull # merge 之前 pull 一下,让 master 更新到和远程仓库同步
git merge feature1合并后的结果push到远端仓库,并删除本地和远端分支feature1
1
2
3git push
git branch -d feature1
git push origin -d feature1也可以使用pull request,查看commit,然后合并分支
rebase 变基
重新设置基础点,切换到branch1变基,防止远端仓库的commit被剔除
1
2git checkout branch1
git rebase master- 回到master,将master移动到最新commit
提交代码错误
- 对最新一条 commit 进行修正
git commit --amend
,替换原来的commit,生成新的一个commit交互式 rebase
rebase -i
:交互式 rebase,是rebase --interactive
缩写,指定某个commit进行修改1
git rebase -i HEAD^^
偏移符合
^
一个或多个这个符号往回偏移对应个数的commit- 偏移符号
~n
向前偏移n个commit 编辑界面,选择commit和对应的操作,将需要编辑的commit的
pick
改为edit
,然后修改需要修改的内容1
2edit beeee 修改...
pick edddd 修改...用
commit --amend
来把修正应用到当前的 commit1
2git add git.txt
git commit --amend继续rebase,把后面的commit直接应用上去
1
git rebase --continue
丢弃重新提交
git reset --hard HEAD^
撤销提交的commit,重新回到上一个commit之前的提交需要丢弃
1
2git rebase -i HEAD^^ 回到上个commit
drop 删掉这个commitgit rebase 第3个commit
会自动选择分岔点,并将4,5commit提交到3所在的路径rebase --onto
额外指定起点,只想把 5 提交到 3 上,不想附带上 41
git rebase --onto 第3个commit 第4个commit branch1
rebase --onto
来撤销提交,起点不包含在rebase序列,下面的例子是丢弃HEAD^,branch1的commit1
git rebase --onto HEAD^^ HEAD^ branch1
push到远端仓库的commit错误
出错的commit已经push到远端分支,需要修改或删除掉,重新修改后,push commit时会报错,因为远端包含本地没有的commit,所以需要忽略冲突,强制push
1
git push origin branch1 -f
出错的commite已经合并到master,不能修改后强制push,应该直接revert撤销commit,然后再push revert后的代码
1
git revert HEAD^
reset
撤销最新提交的commit,其实是重置HEAD,branch的commit位置到父commit
1
git reset --hard HEAD^
可以把HEAD,branch移动其他commit
1
git reset --hard branch2
reset --hard
:重置工作目录,工作目录的修改也被撤销,无论是否已add到暂存区reset --soft
:保留工作目录改动,并将文件的改动放到暂存区- reset 不加参数:工作目录的修改、暂存区的内容以及由 reset 所导致的新的文件差异,都会被放进工作目录
1
2
3
4
5
6
7
8
9
10
11
12
13
14修改了 git.txt 和 readme.md,
并把 git.txt 放进了暂存区
当前push的commit中新增了文件app.txt
此时执行
git reset HEAD^
工作目录的内容都会保存,暂存区被清空
git status
changes not staged:
modified git.txt
modified readme.md
untracked files:
app.txt
checkout
切换分支
git checkout branch1
,也可以切换到指定的commit1
2
3
4
5
6git checkout HEAD^^
git checkout master~3
git checkout 32d434
git checkout 32d434^
checkout -- 文件名 的格式来撤销指定文件的修改reset
HEAD和branch一起移动,而checkout
不会,HEAD会指向新的commit1
2HEAD 和 branch 脱离而不移动 HEAD,HEAD直接指向commit
git checkout --detach
stash
- 将当前改动内容保存到本地其他地方,不会被删除或提交,这样就可以把工作目录的改动清空,所有的改动被保存,之后需要还原的statsh之前的内容,执行
1
2
3
4git stash pop
Git会忽略未被追踪的文件,如果也要stash保存untracked文件,即没有add到缓存区的文件
git stash -u
reflog(reference log)
- 误删了branch1,可以查看HEAD的移动历史,找到删除之前的commit,切换回删除之前的commit,重新创建同名分支,注意reflog要及时,因为不再引用或间接指向的commit会被Git回收
查看其他引用的reflog,git reflog master
1
2
3git reflog
git checkout ccdde32
git checkout -b branch1
gitignore
忽略不需要被管理的文件