Git - Note

版本管理库 Git learning note

Posted by Becks on September 18, 2016
## fetch and merge origin 
git fetch origin/master
git rebase origin/master

#push After rebase
git push --force-with-lease orgin branch1

git clean -fd: remove untracked directories / files.
#-fdL means force removal of untracked files and directories


#This will unstage all files you might have staged with git add:
git reset

#This will revert all local uncommitted changes (should be executed in repo root):
git checkout .

## Throw away all my staged and unstagged changes, forget everything on my current local branch and make it exactly the same as origin/master
git reset --hard origin/master

## reset a single file 
git checkout HEAD -- file.txt

#restore one file from previous commit
git checkout xxxx(headID) -- file.txt


## Compare Branch
git diff branch1 branch2

## Move It can compare files rather than mark as delete and new
git mv file1 file2

## Add/stage by chunk of a file
git add --patch filename

## Revert PR Change 

git revert commitID
git push -u origin branchName

初始化

#设置 global 变量会应用到所有之后建立的git repository
git config --global user.name "Becks"   
git config --global user.email "becks@gmail.com" 

#查看global变量
git config user.name 
git config user.email 

#初始化git repository
git init

#生成一个文件现在repository里,
touch 1.py #并没有添加到管理库当中

#查看当前文件状态, 可以发现哪些文件还没添加到管理空当中, 也可以显示现在修改的文件是不是跟上次commit比被modified
git status
git status -s #显示缩写的状态,红色的M表示还没stage, 绿色的M表示已经stage了
#如果当stage后, 没有commit, 又做了修改, 再git status, 会有两个M, 一个红色,一个绿色

#添加到管理库当中, 让文件变成stage 状态
git add 1.py #再使用 git status, 显示文件已经被可以提交修改了
git add.   #把所有文件都stage

#提交修改 commit 
git commit -m "create 1.py" #-m 自定义更改的信息

#不用add,直接commit; 必须是文件已经被融进仓库了,如果是新文件,还没被融进来,就不行
git commit -am "change 3 in dev"

untracked: git 就根本不知道我们有这个文件,我们要把文件 添加到git 当中; add 文件 就到了staged 状态了, 然后就可以commit,commit之后就变成了unstaged 的状态; unmodified, modified 都是属于unstaged的状态

每次更改文件后需要到先到stage 状态 (git add)才可以commit

记录修改

git log #显示所有更改的commit的信息,比如commit两回,显示两次commit
git log --oneline #显示每个commit用1行
git log --oneline --graph #用图形的方式显示, 当只有一个分支, 会在commit前加上星号成一条线,

#显示现在文件和上次commit的不同
git diff #红色是之前的commit的, 绿色是现在文件

git diff --cached #当文件已经stage, git diff 显示不出不同,需要这句话,显示staged后的文件和上次commit的不同

#当文件stage, 没有commit, 又做了修改,需要下面cmd看不同,如果用git diff --cached,只会显示staged的部分,不会显示又更改的部分
git diff HEAD 

当修改已经被stage (git add) 再看git diff是看不出不同的, 如想看不同需要git diff –cached

回到从前

reset


#本次commit 不会新建commit log,会融进上次commit 的log
#  amend 把stage 状态放在上个commit当中,  no edit是不更改上次commit的评论
git commit --amend --no-edit  #改完之后发现message 没变,但是id是会变的

#返回从stage的状态 到modified的状态
git reset 1.py #把 1.py 返回unstaged的状态

#把commit的过后的版本返回到之前的状态, 调整head 到上一个,上上一个; 
git reset --hard HEAD #把head 移到了移动到之前commit上面,remove所有本次的修改 
                        #git status会显示没有任何修改了

git reset --hard HEAD^ #把head 移到前一个commit, 
git reset --hard HEAD^^ #移到前两个commit


git reset --hard 7a7ecea #把head 移到 7a7ecea这个id上面去 (看id: git status --oneline)
#再git status --oneline 就不能看7a7ecea之后的commit的

## reset 几个file 到之前的head
git checkout 7a7ecea -- 1.py 2.py

## revert to head 之前一个commit
git checkout 7a7ecea~1 -- 1.py 2.py

#也可以把head回到未来, 从上上个移动到现在的
git reflog #看每一个的变化, 显示每一个head的移动
git reset --hard 3f27543 #通过reflog 找到想返回之后的head id,可以返回了
git reset --hard HEAD@{0} #也可以把之前复制过来

checkout

#只让一个文件回到过去
git checkout 7a7ecea -- 1.py   # -- 只有有空格
#7a7ecea是之前commit的id,  只恢复1.py; 2.py 还是现在的状态
#之后修改再commit, 会建立新的commit的,git log --oneline 显示这次在过去的commit上面,过去的commit不会像reset一样消失

如果更改了file, 但还没有stages, 可以用恢复当前的files

git checkout .

管理分支

比如master是client用的,要稳定版,自己要用一个开会的分支

#方法一:
git branch dev #建立一个名为dev的,head还在master
git checkout dev #head切换 dev, 再git branch, dev分支上显示星号

#方法二
git checkout -b dev #建立一个名为dev的, 并把head移动到dev分支上

#查看分支
git branch #显示现在所有的分支, 星号表示现在的分支

#删除分支
git checkout master 
git branch -d dev #删除dev的分支, 报错,因为现在就在dev分支上, 先切换别的分支,才能删除
git branch -D dev #如果git branch -d dev, 大写的D表示强行删除

# Merge
git checkout master #保证在master上,merge时候不能在dev branch上

git merge --no-ff -m "keep merge in info" dev 
#把dev merge到master上来, -m "keep merge in info"把信息记录在log
# --no-ff, no faster forward, 默认是faster forward是不会留信息

#merge 之后再看git log --oneline --graph #会有图像显示branch的分支产生,merge

分支冲突

Merge

比如 两个分支master, dev各有修改, 当git merge dev 时候有conflict, 然后file里显示什么冲突了

  1. 把冲突的部分删除掉,做修改,修改过后的状态是modified,
    • 方法一: stage (git add .) 再commit(git commit -m “solve conflict”)
    • 方法二: 直接 git commit –am “solve conflict”
  2. 再git log –oneline –graph 会显示两个分支合并了

在master 和 dev上有改变,然后合并了两个分支

rebase : 重新基于主分支的内容

Branch B 为主分支,然后有天有人提交了bug的修改, 在主分支branch b的上进行了提交,

比如我在branch A上工作,在c3, 这时如果想把bug融合到c3上;

方法是: 先把branch A的c3拿走,空出来, 把c2,c4合并到上面去, 再把c3放到合并以后的地方, 注:现在c3基于c4, 以前的c3不复存在了 所以rebase是危险的方式, rebase 后c3的commit id和rebase前c3的id是不一样的

#先checkout master,然后再主分支的修改基于dev的修改 (上图的branch A是master, branch b是dev)
git checkout master
git rebase dev #(把master分支基于dev分支)
#如果有conflict, 跟merge一样的, 去修改conflict
#修改完conflict, git branch  发现不在master 和dev的任何一个分支上, 在一个新的分支上rebasing master上

#stage + commit 
git add 1.py
git rebase --continue #继续rebase
#如果碰到conflict,想放弃rebase
git rebase --abort

git log --oneline --graph #会发现dev的commit插到master上面来了,

最上面是master 的log, 下面的是dev的log

rebase 和 merge 不一样,dev上commit 的内容被插进master的分支上, 而不是分成两个branch 再merge, c3重新基于刚修改的dev的分支,注意change4 master的ID 和 之前的ID不一样的

临时修复

比如要改之前的程序, 而现在的改进程序还没有完成, 不想把改进的和要改的程序放在一起, 用stash可以改进的code暂存一下而不用commit。 等改后之前的, 再继续工作, 有不同的commit, 不会有冲突

git checkout dev
#git status -s 显示文件已经被更改
git stash #把现在的文件放在缓存区
git status -s #此时就没有任何的modified 文件了

stash之后,看status不会显示modified的内容

#此时接到电话,给老板写代码
#此时再建一个新的branc: git checkout -b boss; 在这个branch中修改之前的code, stash缓存的更改不会建立在这个branch中

#修改完boss分支后, 再checkout 回dev: 
git checkout dev #回到dev,显示上次commit的内容,不会显示上次修改stash的内容
git stash pop #就会把之前修改暂存的返回回来

当stash后再建立新的branch, stash缓存的内容不会出现的新的branch中, 新的branch只显示上次commit 的内容

GitHub

git push -u origin master #把master分支推到origin上面, origin指得是online的管理库
git push -u origin dev #把dev分支推到origin上面

git config --get remote.origin.url #查看remote url

#修改已经存在的origin为新的http://....
git remote set-url origin https://  #已经有remote url,改变现有的url
git remote add origin https://      #初始url

origin指得是online的管理库, history显示所有的改变, change显示每次commit发生变化, 本地的.git文件也被上传到管理库