uniquejava / blog

My notes regarding the vibrating frontend :boom and the plain old java :rofl.
Creative Commons Zero v1.0 Universal
11 stars 5 forks source link

git and github #16

Open uniquejava opened 8 years ago

uniquejava commented 8 years ago

和RTC的比较: Guide to Git for Rational Team Concert users

猴子都能懂的Git: https://backlog.com/git-tutorial/cn/

大量的github文档: https://help.github.com/categories/collaborating-with-issues-and-pull-requests/

两种工作流程: GitHub Flow and Git Flow are the two most common Git patterns.

设置代理


## 给git全局设置proxy
git config --global http.proxy http://proxy.xx.xx.com:8080

## 全局取消proxy
git config --global --unset http.proxy

## 查看git当前使用的proxy
git config --global --get http.proxy

## 单独给某一次设置proxy (比如给git fetch upstream设置)
git -c http.proxy=http://proxy.xx.xx.com:8080 fetch upstream

## 来个alias呗
alias gitt='git -c http.proxy=http://proxy.xx.xx.com:8080'

1. github flow

See Understanding the GitHub Flow

又分为两种 Model: Fork & Pull Model, 以及 Shared Repository Model. 详见: About collaborative development models

我们项目用的Fork & Pull Model

git fetch upstream master 
git checkout master 
git merge upstream/master 
git checkout -b your_branch_name 
make modification 
git add . 
git commit -m "...." 
git fetch upstream  master 
git rebase -i upstream/master 
测试.
git push origin your_branch_name 
login github, switch to the branch , compare
检查commit是否只有一次,检查变动的文件是否为你期望提交的.
 send PR

还有一种适合小团队用的Shared Repository Model

see GitHub Collaboration Using the Shared Repository Model and the embedded link there.

套路

git status

如果所有的文件都要提交, 跳过此步
如果新加的但是没用的文件,  先用rm命令删除 然后git add
如果文件是有用的,但是不想提交(比如某个配置文件) 使用git ingore file_name

git add .
git commit -m "xxxx"
git pull --rebase
git push origin master

2. git flow

See A successful Git branching model

关于PR

详见:https://help.github.com/articles/about-pull-requests/

需要特别注意的两点: Note: When working with pull requests, keep the following in mind:

  1. If you're working in the shared repository model, we recommend that you use a topic branch for your pull request. While you can send pull requests from any branch or commit, with a topic branch you can push follow-up commits if you need to update your proposed changes.
  2. When pushing commits to a pull request, don't force push. Force pushing can corrupt your pull request.
uniquejava commented 8 years ago

git rebase及合并冲突

将多个commit合并成一次, 只要将除第一次pick之后的那pick全部替换成s即可。替换成s的commit会自动合并到标记为pick的那一次提交。如下:

执行git rebase -i upstream/master

pick afafafdf232raf
pick 12312321wd
pick afaf23rwef3e
pick 13ewqdwad

要把后面三个pick批量替换成改成s, 可以使用如下快捷命令(将2-4行的pick改成s)

:2,4s/pick/s
:wq

保存后提示有冲突 git status查看冲突的文件有哪些,用webstorm逐个打开这些文件,找到所有的<<<(command + f)

<<<<<HEAD
code on head
======
code on some branch
>>>>>>>SOME_BRANCH

比较===上面和===下面的代码,看哪个是对的。 比如我会command+d(删除行)只留下code on head这一段(表示===上面的这段代码是正确的) 保存,打开下一个冲突的文件。修改所有出现<<<的地方。。。

所有的文件改完后 使用git add .提交变化(相当于svn中的mark as resolved) 然后 git rebase --continue 如果还有冲突, 重复以上步骤,直到git status全部变绿。。

(在任意时候,如果想撤消所有的变更,使用git rebase --abort)

最后git push origin branch_name -f

使用服务上的某个文件覆盖本地的某个文件

git checkout origin/master -- router/router.js

uniquejava commented 7 years ago

克隆代码

git clone https://path/to/xx.git --depth 1 -b branch_name local_dir_name 比如 git clone https://github.com/jquery/jquery.git --depth 1 -b 1.12-stable jq1.x 只保留最后一条history, 只下载1.12-stable分支, 放在当前目录jq1.x这个子目录中.

增删改查CRUD

git add . git add a.txt b.js c.java git add .txt git status -s git diff 比较working directory和index git diff hello.txt 仅比较某个文件 git diff --staged 比较index和最后一次commit git diff HEAD 比如working directory和最后一次commit git commit -a -m "message" 跳过暂存区一键提交 git checkout -- dir_name 撤销对某个目录所做的变更(危险) git checkout -- .log 撤销对某类文件所做的变更(危险) git checkout -- . 撤销对所有文件所做的变更(危险) git reset HEAD hello.txt 从暂时区移除某个文件, git add的逆反操作(安全) rm abc.txt 删除未track的文件 git rm abc.txt -f 从暂存区连同本地一起删除 详见: 这里

查看历史

git log git log -p -2 快速浏览最近两次commit所带来的变化 git log --stat 查看最近改了哪些文件 git log --pretty=format:"%h - %an, %ar : %s" 指定log格式,类似github commit上看到的内容 git log --since=2.days --oneline 只列出最近两天的 详见: 这里 git log --follow resource/adic/filename.fdic.xml.bak 查看某个文件的变更历史 git show REVISION:/path/to/file 查看某个指定版本下的文件内容 git diff b4d8628^^..b4d8628 resource/adic/filename.xml.bak 比较某次版本变更中某个文件的变化

撤销git reset

详见: https://stackoverflow.com/questions/927358/how-to-undo-the-last-commits-in-git

适用于commit了但未push

最常用: git reset HEAD~1 (只保留working area)

完全重置: git reset --hard HEAD~1

最不常用: git reset --soft HEAD~1 (保留index和working area)

git对于remote别名的管理

git remote -v(显示remote列表) git remote add remote_branch_name url (默认的remote_branch_name为origin) git remote show origin(显示某remote详情) git remote rename origin osc (重命名) git remote rm github (删除某个remote branch) git clone -o osc http://git.oschina.net/~ (不喜欢默认origin时这样clone)

git对于branch的管理

git branch (查看当前所处的branch) git branch -a (列出所有的branch, 包括remote) git branch revert_branch HEAD^(基于某个commit id建新分支) git checkout revert_branch(切换到某个分支) git checkout -b mybranch(基于当前commit id新建branch并切换到新分支) git checkout -b revert-branch HEAD^(基于某commit id新建分支) git branch -d mybranch(删除本地branch) git branch -m old_branch new_branch(重命名本地branch) git merge mybranch(将mybranch合并到当前所在的branch) git push origin mybranch (推送本地branch到远程) git push origin local_branch_name: remote_branch_name) (推送本地branch到远程另一个branch) git push origin :mybranch(删除远程branch)

git对于tag的管理

git checkout xx_tag(切换到xx_tag) git tag v0.1 (给当前版本创建轻量标签,不需要使用 -a、-s 或 -m 选项,只需要提供标签名字) git tag -a v1.2 9fceb02 (给某个版本打标签, 后期打标签) git tag -a v0.1 -m "a runnable version." (将当前版本打标签) git tag(列出所有的tag) git tag -l "v0.*" 显示某些tag git show v0.1(显示某个tag) git tag -d v0.1(删除某个tag) git push origin v0.1(将tag v0.1推向服务器) git push origin --tags(将所有的tag推向服务器) git checkout -b version2 v2.0.0 (不能真正的检出标签,只能基于某tag创建分支,如果分支上代码有变更, 注意此时tag和branch代码就不一致了)

删除Tag

如果tag有一个唯一的名字 git tag -d [tag]; git push origin :[tag]

如果tag刚好和branch同名, 则使用下面的命令删除tag.

git tag -d [tag] git push origin :refs/tags/[tag]

git ignore

见: How do I configure git to ignore some files locally? 见: Git - Difference Between 'assume-unchanged' and 'skip-worktree'

1. 如何忽略在某些本地修改的文件(只针对本人)

往.gitconfig文件的 [alias] 部分添加一些alias(直接使用下面的命令也可)

git config --global alias.ignore 'update-index --skip-worktree'
git config --global alias.unignore 'update-index --no-skip-worktree'
git config --global alias.ignored '!git ls-files -v | grep "^S"'

现在, 你可以使用如下git ignore命令来管理这些文件了.

git ignore config.xml
        git will pretend that it doesn't see any changes upon config.xml — preventing you from accidentally committing those changes.

git unignore config.xml
        git will resume acknowledging your changes to config.xml — allowing you again to commit those changes.

git ignored
        git will list all the files which you are "ignoring" in the manner described above.

2. assume-unchanged和skip-worktree的区别

简而言之, assume-unchanged 是为了提高性能, 告诉git, developer永远都不会去修改某个文件(比如SDK文件夹)

skip-worktree 是告诉git, developer会在本地添加/修改某个文件, 求你不要track这个文件(不管是在repo已经存在的还是用户新增), 即使用git reset --hard也不要去覆盖这个文件.

3. --skip-worktree 和 .git/info/exclude的区别

--skip-worktree 针对已经track或未track的文件均有效, 而.git/info/exclude只对未track的文件有效

查看

git show commit_id git log --oneline --graph git log --oneline -Ssearch_string_here

其它

git config --list 列出所有的配置项
git config user.name 查看某一项配置 git config --global user.name "cyper" git config --global user.email "3453**@qq.com" git config --global core.autocrlf true/input (对换行符的处理, windows上设置为true,其它平台设置为input) git checkout -- file_name (撤销本地的变更,file_name可以是通配符,比如.txt) git commit --amend 重做最后一次提交 git reset 清空index区(撤销所有的git add) git reset file_name 撤销单个文件的git add git reset -i HEAD~3 和 git rebase -continue(每次向下一个commit前进一步) git diff 比较working directory和index git diff --staged 比较index和最后一次commit git diff HEAD 比如working directory和最后一次commit

git别名

git config --global alias.co checkout git config --global alias.br branch git config --global alias.ci commit git config --global alias.st status git config --global alias.unstage 'reset HEAD --' 这会使下面的两个命令等价: $ git unstage fileA $ git reset HEAD -- fileA git config --global alias.last 'log -1 HEAD'

uniquejava commented 7 years ago

git中merge和rebase的区别

使用git也有两年的时间了。以前带我的同事,让我在拉代码的时候要我使用git pull --rebase,一直很纳闷为什么要那样做,后来遇到拉代码的时候有许多冲突要解决,然后去查找资料,才了解到其中的一些事情。今天分享一下,顺便自己也梳理一下。 git pull git pull 是 git fetch + git merge FETCH_HEAD 的缩写。所以,默认情况下,git pull就是先fetch,然后执行merge 操作,如果加–rebase 参数,就是使用git rebase 代替git merge。 merge 和 rebase merge 是合并的意思,rebase是复位基底的意思。 现在我们有这样的两个分支,test和master,提交如下:

      D---E test
     /
A---B---C---F master

在master执行git merge test,然后会得到如下结果:

      D--------E
     /          \
A---B---C---F----G   test, master

在master执行git rebase test,然后得到如下结果:

A---B---D---E---C'---F'   test, master

可以看到,merge操作会生成一个新的节点,之前的提交分开显示。而rebase操作不会生成新的节点,是将两个分支融合成一个线性的提交。

其他内容放这里

通过上面可以看到,想要更好的提交树,使用rebase操作会更好一点。这样可以线性的看到每一次提交,并且没有增加提交节点。 在我们操作过程中。merge 操作遇到冲突的时候,当前merge不能继续进行下去。手动修改冲突内容后,add 修改,commit 就可以了。 而rebase 操作的话,会中断rebase,同时会提示去解决冲突。解决冲突后,将修改add后执行git rebase –continue继续操作,或者git rebase –skip忽略冲突。

uniquejava commented 7 years ago

永久删除某个senstive的文件

比如我想删除src/assets/bg.png.

git filter-branch --force --index-filter \
'git rm --cached --ignore-unmatch src/assets/bg.png' \
--prune-empty --tag-name-filter cat -- --all

详见: https://help.github.com/articles/removing-sensitive-data-from-a-repository/

改最后一次提交的作者

git commit --amend --author="Philip J Fry <someone@example.com>"

https://makandracards.com/makandra/1717-git-change-author-of-a-commit

改某次提交的作者

写得非常详细: https://stackoverflow.com/questions/3042437/change-commit-author-at-one-specific-commit

Interactive rebase off of a point earlier in the history than the commit you need to modify (git rebase -i <earliercommit>). In the list of commits being rebased, change the text from pick to edit next to the hash of the one you want to modify. Then when git prompts you to change the commit, use this:

git commit --amend --author="Author Name <email@address.com>"

For example, if your commit history is A-B-C-D-E-F with F as HEAD, and you want to change the author of C and D, then you would...

  1. Specify git rebase -i B (here is an example of what you will see after executing the git rebase -i B command)
    • if you need to edit A, use git rebase -i --root
  2. change the lines for both C and D from pick to edit
  3. Once the rebase started, it would first pause at C
  4. You would git commit --amend --author="Author Name <email@address.com>"
  5. Then git rebase --continue
  6. It would pause again at D
  7. Then you would git commit --amend --author="Author Name <email@address.com>" again
  8. git rebase --continue
  9. The rebase would complete.

同时有两条精彩的评论:

  1. 可以加--no-edit参数,. git commit --amend --reset-author --no-edit这样就不会打开editor.
  2. 如果要rebase首次提交的内容, 使用  git rebase -i --root

批量修改作者

see stackoverflow, One liner, but be careful if you have a multi-user repository - this will change all commits to have the same (new) author and committer.

git config user.name xxx
git config user.email yyy
git filter-branch -f --env-filter "GIT_AUTHOR_NAME='yinsb'; GIT_AUTHOR_EMAIL='yinsb@xx.com'; GIT_COMMITTER_NAME='yinsb'; GIT_COMMITTER_EMAIL='yinsb@xx.com';" HEAD

第一次要使用git pull origin master --rebase

git cherry-pick

注意针对某个 commit id, cherry-pick会重新生成一个新的commit id, 常用命令如下:

git cherry-pick commit-id (单次)
git cherry-pick from..to (不包含from)
git cherry-pick from^..to  (包含from)
git cherry-pick --continue (解决冲突后继续)
git cherry-pick --abort (回到cherry-pick之前的状态)
git cherry-pick --quit (放弃本次commit-id)
git cherry-pick不能直接作用于merge类型的commit,  要加-m参数.

The synopsis is git cherry-pick [--edit] [-n] [-m parent-number] [-s] [-x] [--ff] <commit>... git cherry-pick goes from left to right commit. You can order how you want. If you have a conflict you have three choices. you can git cherry-pick --quit (stop cherry-picking and let your tree in his current state), git cherry-pick --abort (stop cherry-picking and reset your branch to the state where he was before you start git cherry-pick) or resolve this conflict with an editor or with git mergetool and then git cherry-pick --continue go to next commit in your list.

see https://stackoverflow.com/questions/20698614/multiple-commits-cherry-picking

Todo

git submodules ~git cherry-pick~ ~git ignore in depth~ git web hooks

uniquejava commented 6 years ago

There is no tracking information for the current branch

There is no tracking information for the current branch

You could specify what branch you want to pull:

git pull origin master

Or you could set it up so that your local master branch tracks github master branch as an upstream:

git branch --set-upstream-to=origin/master master
git pull

This branch tracking is set up for you automatically when you clone a repository (for the default branch only), but if you add a remote to an existing repository you have to set up the tracking yourself. Thankfully, the advice given by git makes that pretty easy to remember how to do.

Generate public key

很多初次使用者问到的问题link列在这: https://git-scm.com/book/en/v2/Git-on-the-Server-Generating-Your-SSH-Public-Key

cd ~/.ssh
ls
ssh-keygen -o
cat ~/.ssh/id_rsa.pub

fatal: Could not read from remote repository.

如果碰到, 这里有N多解决方案: https://stackoverflow.com/questions/13509293/git-fatal-could-not-read-from-remote-repository

uniquejava commented 5 years ago

github branch protection rule

如何应用到多个branch

*   匹配所有分支
[md]*  匹配分支名以m或d开始的
[md][ae]* 匹配分支名第一个字母为m或d, 第二个字母为a或e,这样即能匹配master也能匹配dev.

来源: https://stackoverflow.com/a/55303944/2497876

uniquejava commented 4 years ago

GIt reflog

git reflog 找到曾经正确的那次提交的id: xxxx git checkout xxxx

然后你懂的

uniquejava commented 4 years ago

批量删除github上所有的tag

It may be more efficient to push delete all the tags in one command. Especially if you have several hundred.

In a suitable non-windows shell, delete all remote tags:

git tag | xargs -L 1 | xargs git push origin --delete

Then delete all local tags:

git tag | xargs -L 1 | xargs git tag --delete