Thursday, July 2, 2015

Git Best Practices and Commands + Misc



Chrome extension for github - display GitHub code in tree format
https://chrome.google.com/webstore/detail/octotree/bkhaagjahfmjljalopjnoealnfndnagc?hl=en-US
https://github.com/buunguyen/octotree

How to make it work with enterprise
https://github.com/buunguyen/octotree/issues/8
http://sushihangover.github.io/git-set-up-a-fetch-only-remote/
 git remote set-url --push upstream DISABLE
 git remote set-url --push redux DISABLE
git remote show origin
In git 2.0, git branch --unset-upstream will prevent git push working against the current branch. 

http://stackoverflow.com/questions/7419244/elegant-solution-to-prevent-force-push-on-master-only
Github
Adding an existing project to GitHub using the command line
git init
git remote add origin <remote repository URL>
git push origin master

Check out a remote branch in git
If you would like to checkout the branch groups, you can simply say this in recent versions of Git:

git fetch origin
git checkout groups
This will automatically track origin/groups from a local branch groups.

authentication cache
git config --global credential.helper 'cache --timeout 72000'
git credential-osxkeychain erase

https://ariejan.net/2009/10/26/how-to-create-and-apply-a-patch-with-git/
If you fix a bug or create a new feature – do it in a separate branch!
git clone git://github.com/ariejan/imdb.git
cd imdb
git checkout -b fix_empty_poster
Now, in the new fix_empty_poster branch you can hack whatever you need to fix. Write tests, update code etc. etc.
git log --pretty=oneline -3
git format-patch master --stdout > fix_empty_poster.patch
This will create a new file fix_empty_poster.patch with all changes from the current (fix_empty_poster) against master. Normally, git would create a separate patch file for each commit, but that’s not what we want. All we need is a single patch file.
git apply --stat fix_empty_poster.patch
Note that this command does not apply the patch, but only shows you the stats about what it’ll do. After peeking into the patch file with your favorite editor, you can see what the actual changes are.
Next, you’re interested in how troublesome the patch is going to be. Git allows you to test the patch before you actually apply it.
git apply --check fix_empty_poster.patch
If you don’t get any errors, the patch can be applied cleanly. Otherwise you may see what trouble you’ll run into. To apply the patch, I’ll use git am instead of git apply. The reason for this is that git am allows you to sign off an applied patch. This may be useful for later reference.
git am --signoff < fix_empty_poster.patch
Applying: Added specs to test empty poster URL behaviour
Applying: Added poster URL as part of cli output
Clone a specific Git branch
git clone -b my-branch https://git@github.com/username/myproject.git
git log
git log filepath
git log -p filename
to let git generate the patches for each log entry.
However, from the command line, you can find any commits that introduced or removed lines mentioning get_info with the -S option to git log. e.g.:
git log -Sget_info -p
(n.b. there should be no space between -S and the search term)
So, at a minimum that should find the commit where the function was first introduced and the one that removed it. I added the -p so you can also see the patches - if lots of commits introduced changes that mentioned the function that may be helpful. If the function was only on another branch it might also be useful to use --all to search all branches.
git: diff between file in local repo and origin
git diff origin/master -- [local-path]
How to check if a local repo is up to date?
git fetch --dry-run
http://stackoverflow.com/questions/2514270/how-to-check-for-changes-on-remote-origin-git-repository
it remote update to bring your remote refs up to date. Then you can do one of several things, such as:
  1. git status -uno will tell you whether the branch you are tracking is ahead, behind or has diverged. If it says nothing, the local and remote are the same.
  2. git show-branch *master will show you the commits in all of the branches whose names end in master (eg master and origin/master).
If you use -v with git remote update you can see which branches got updated, so you don't really need any further commands.
temporarily ignoring files
So, to temporarily ignore changes in a certain file, run:
git update-index --assume-unchanged <file>
Then when you want to track changes again:
git update-index --no-assume-unchanged <file>
https://coderwall.com/p/gjp15g/git-temporarily-ignoring-files
[alias] ignore = !git update-index --assume-unchanged unignore = !git update-index --no-assume-unchanged ignored = !git ls-files -v | grep ^[a-z]
Can I get a list of files marked --assume-unchanged?
git ls-files -v|grep '^h'
% git ls-files -v
h a.txt
H b.txt
If the first character is lowercase, it is marked as "assume unchanged", in this case a.txt. See also the man page of ls-files.

How can I see what I am about to push with git?
Viewing Unpushed Git Commits
git diff origin/master..HEAD
git diff --stat --cached origin/master
git diff [remote repo/branch]

git checkout discover
Git Diff
http://stackoverflow.com/questions/6879501/filter-git-diff-by-type-of-change
git diff --name-only  -- *.java
http://stackoverflow.com/questions/5432396/create-a-patch-by-comparing-a-specific-branch-on-the-remote-with-a-specific-loca
Create the patch:
git log --pretty=oneline -3
git format-patch master --stdout > fix_empty_poster.patch

Use git format-patch origin/master. This creates a patch file for each commit on your checked out branch, which is not in origin/master.
https://ariejan.net/2009/10/26/how-to-create-and-apply-a-patch-with-git/
git apply --stat fix_empty_poster.patch
git apply --check fix_empty_poster.patch
 I’ll use git am instead of git apply. The reason for this is that git am allows you to sign off an applied patch. This may be useful for later reference.
git am --signoff < fix_empty_poster.patch Understanding Git conflict markers
When looking at Git conflict markers it can sometimes be confusing which half of the conflicting section belongs to which branch:
<<<<<<< HEAD
foo
=======
bar
>>>>>>> cb1abc6bd98cfc84317f8aa95a7662815417802d
  • the top half is the branch you a merging into
  • the bottom half is from the commit that you are trying to merge in
What this means in practice if you are doing something like git pull (which is equivalent to a git fetch followed by a git merge) is:
  • the top half shows your local changes
  • the bottom half shows the remote changes, which you are trying to merge in
On the other hand, if you are doing something like git rebase origin/master, you are effectively trying to merge your local changes "into" the upstream changes (by replaying them on top); that means:
  • the top half shows the upstream changes
  • the bottom half shows your local changes, which you are trying to merge in

Work with pull request
Checking out pull requests locally
At the bottom of the pull request, click command line. Follow the sequence of steps to bring down the proposed pull request.

Stash change:
Tips for using a git pre-commit hook
Keep your hook script in source control
ln -s ../../pre-commit.sh .git/hooks/pre-commit

Stash unstaged changes before running tests
git stash -q --keep-index
...
git stash pop -q
The -q flags specify quiet mode.

alias gc='git commit'
alias gcv='git commit --no-verify'


Maven pre-commit

Git Hooks
Enforce code standards with composer, git hooks, and phpcs
http://tech.zumba.com/2014/04/14/control-code-quality/
STAGED_FILES_CMD=`git diff --cached --name-only --diff-filter=ACMR HEAD | grep \\\\.php`
# Determine if a file list is passed
if [ "$#" -eq 1 ]
then
oIFS=$IFS
IFS='
'
SFILES="$1"
IFS=$oIFS
fi
SFILES=${SFILES:-$STAGED_FILES_CMD}

Yelp pre-commit
http://pre-commit.com/
http://pre-commit.com/hooks.html
https://github.com/pre-commit/pre-commit
Run pre-commit install to install pre-commit into your git hooks. 

.pre-commit-config.yaml

Use Git Pre-commit Hooks to Stop Unwanted Commits
Git Autocompletion for your shell
source `brew --prefix git`/etc/bash_completion.d/git-completion.bash
If the pre-push script exits with a failure (a return status of non-zero) then the push will do nothing. 
git push --no-verify

git config --global user.name "Markus Prinz"
git config --global user.email "markus.prinz@nuclearsquid.com"

Git diff
$ git diff --cached   (2)
$ git diff HEAD       (3)
Changes between the index and your last commit; what you would be committing if you run "git commit" without "-a" option.
Changes in the working tree since your last commit; what you would be committing if you run "git commit -a"















Limiting the diff output
$ git diff --diff-filter=MRC            (1)
$ git diff --name-status                (2)
$ git diff arch/i386 include/asm-i386   (3)
  1. Show only modification, rename, and copy, but not addition or deletion.
  2. Show only names and the nature of change, but not actual diff output.
  3. Limit diff output to named subtrees.
$ git diff topic master    (1)
$ git diff topic..master   (2)
$ git diff topic...master  (3)
  1. Changes between the tips of the topic and the master branches.

git-stash(1)

git stash is something that can be incredibly handy. What it does is very simple: If you run git stash save, it will take all the changes you have in your working directory and the index, and save them away, leaving you with a clean working directory. Once you’ve done what you wanted to do, you can restore your changes by running git stash pop.
clear
Remove all the stashed states. Note that those states will then be subject to pruning, and may be impossible to recover (...).

git stash drop takes no parameter - which drops the top stash - or a stash reference which looks like: stash@{n} which n nominates which stash to drop. You can't pass a commit id to git stash drop.
GIT BRANCH
https://git-scm.com/book/en/v2/Git-Branching-Branch-Management
$ git branch --no-merged
This shows your other branch. Because it contains work that isn’t merged in yet, trying to delete it with git branch -d will fail:
$ git branch -d testing
$ git merge hotfix
git branch -d iss53
git rev-parse --abbrev-ref HEAD
git rev-parse is an ancillary plumbing command primarily used for manipulation.
One common usage of git rev-parse is to print the SHA1 hashes given a revision specifier. In addition, it has various options to format this output such as --short for printing a shorter unique SHA1.

https://www.atlassian.com/git/tutorials/undoing-changes/git-reset

git reset <file>
Remove the specified file from the staging area, but leave the working directory unchanged. This unstages a file without overwriting any changes.

git revert

The git revert command undoes a committed snapshot. But, instead of removing the commit from the project history, it figures out how to undo the changes introduced by the commit and appends a new commit with the resulting content. This prevents Git from losing history, which is important for the integrity of your revision history and for reliable collaboration.



MISCS
git rev-parse --abbrev-ref HEAD
That will display the current branch

"git branch" should show all the local branches of your repo. The starred branch is your current branch.

Dangerous
You did it the wrong way around. You are meant to reset first, to unstage the file, then checkout, to revert local changes.
Try this:
$ git reset foo/bar.txt
$ git checkout foo/bar.txt
Symbolic link to a hook in git
http://stackoverflow.com/questions/4592838/symbolic-link-to-a-hook-in-git
ln -s -f ../../hooks/post-merge .git/hooks/post-merge

This. When git is evaluating the symlink, it apparently does so using .git/hooks as its working directory, so relative paths should be relative to that directory. This is more self-explanatory if you first cd into .git/hooks before making the symlink, and figure out the relative path from there. –  Eliot Feb 6 '14 at 19:57

https://gist.github.com/chelmertz/816166

http://www.vogella.com/tutorials/EclipseGit/article.html
To see the history of a resource, select your project, a file or a folder, right-click on it and select the Show in → History context menu entry. Alternative you can use the Alt+Shift+W shortcut and select the History entry.

28.1. The Eclipse Mylyn plug-in
You can integrate your GitHub issues into Eclipse via File → Import... → Task → GitHub Task Repositories and by following the wizard.

http://stackoverflow.com/questions/10627389/diff-current-file-version-and-previous-one-remote-repository
f you want to restrict the diff to just a file or to all files in a directory use:
git diff <remote>/<branch> -- /path/to/file
git diff <remote>/<branch> -- /path/to/           #all files in directory
You can use git difftool ... to start a visual diff tool (assuming one exists on your machine).
git: how to update (checkout) a single file from remote origin master
git checkout origin/master -- path/to/file

https://coderwall.com/p/xszmda/set-up-a-read-only-remote-on-git
Create a remote (or use an existing one) and set its push url to something funny.

git remote add origin-readonly https://url.to/remote.git
git remote set-url origin-readonly --push "You shall not push"


Search github:
As a result, you need to specify a special media type in the Accept header to get things working.
Give this a try:
curl -i -H "Accept: application/vnd.github.preview+json" -H "Authorization: token <token>" https://github.mycompany.com/api/v3/search/code?q=class


git ls-files '.DS_Store'
As long as you don't include a slash, it is matched against the file name in all directories.
.DS_Store
# remove any existing files from the repo, skipping over ones not in repo
find . -name .DS_Store -print0 | xargs -0 git rm --ignore-unmatch
DS_Store is the name of a file in the Apple OS X operating system for storing custom attributes of a folder such as the position of icons or the choice of a background image.[1] The name is an abbreviation ofDesktop Services Store

# return the line number where the match was found
PS:\> git grep -n monkey

# return just the file names
PS:\> git grep -l monkey

# count the number of matches in each file
PS:\> git grep -c monkey
http://stackoverflow.com/questions/277546/can-i-use-git-to-search-for-matching-filenames-in-a-repository
git ls-files will give you a listing of all files in the repository. You can pass a pattern in to get files matching that pattern.git ls-files '*/HelloWorld.pm'
git ls-files "*middleware*"

If you would like to find a set of files and grep through their contents, you can do that with git grep:git grep some-string -- '*/HelloWorld.pm'
http://www.barretlee.com/blog/2015/09/06/set-gitignore-after-add-file/
  1. 如果一个匹配 pattern 后面有一个斜杠,如 foo/,则默认会匹配所有(包含父子文件夹)中的 foo 文件夹内容,并且它不会匹配单个的文件;
  2. 如果一个匹配 pattern 不包含斜杠,如 foo,Git 会将其作为一个 shell 的查找命令匹配内容。
  • 如果一个 pattern 以 ** 开头,如 **/foo,最后会匹配所有文件夹下的 foo 文件(夹);
  • 如果一个 pattern 以 /** 开头,如 abc/**,则表示匹配 abc 目录下的所有内容;
  • 如果一个 pattern 中间包含 **,如 a/**/b,则会匹配a/ba/x/ba/x/y/b 以及所有类似的内容。
# 这一步的操作相当于回到 git add 上一步
git rm -r --cached .
After fix conflict in code:
run git add , to resolve the conflict.

Github
Expand all "outdated diff" comments in a GitHub pull request
expand all those collapsed comments
javascript:(function(){$(".outdated-diff-comment-container").addClass("open");}());


if you want to expand just your own comments, use this:javascript:(function(){$(".outdated-diff-comment-container").filter(function () { return this.firstElementChild.textContent.indexOf("peterflynn") !== -1; }).addClass("open");}());

https://github.com/blog/1492-repository-search-on-all-repositories
In code search page, To search globally, all you need to do is select the All repositories option:

Git - deleted some files locally, how do I get them from a remote repository
Since git is a distributed VCS, your local repository contains all of the information. No downloading is necessary; you just need to extract the content you want from the repo at your fingertips.
If you haven't committed the deletion, just check out the files from your current commit:
git checkout HEAD <path>
If you have committed the deletion, you need to check out the files from a commit that has them. Presumably it would be the previous commit:
git checkout HEAD^ <path>
but if it's n commits ago, use HEAD~n, or simply fire up gitk, find the SHA1 of the appropriate commit, and paste it in.
http://prismoskills.appspot.com/lessons/Git/Chapter_02_-_File_management_in_Git.jsp
Major difference between git and other VCSs is that git copies all versions of all files to every local repository.
This is unlike other VCSs which store incremental differences between versions in a central repository.
For performance, Git makes a copy of a file only if its changed else it just stores a link to the older file.

A file in git goes through the following stages:
 
git add puts a snapshot of the file to the staging area.
Further modification to the file will not be committed with git commit unless a git add is done again.

git diff compares local file to the staged file.
git diff --staged compares staged file to the committed file.
=> if you have staged all your changes, then git diff will give no output but git diff -- staged will show you all the changes.

Removing a file
rm foo
git rm foo
git commit foo

If you accidentally staged a file, it can be removed from the staging area by
git rm --cahced foo
This keeps the file in your local directory but removes it from staging area.

Moving a file
git mv src.txt dest.txt
git considers moving a file as renaming a file.
This is useful because the file history is preserved on rename.
Debugging with git
http://prismoskills.appspot.com/lessons/Git/Chapter_12_-_Debugging_with_git.jsp
Use git blame to see when each line of the method was last edited and by whom.
Use -L option to limit the output to specified lines.
git blame -L 5,20 foo.txt

Binary search through commits.
Git provides a binary search command to help you find a misbehaving commit.
git bisect start
git bisect bad (tells git that current version is broken)
git bisect good v1 (tells git that good version known to you is v1)
// At this point, git knows good and bad versions and sets HEAD to the middle of these two versions
// run your test on this version
git bisect good (tells git that test passed and current version set by git has no issues)
// Now also, git knows good and bad versions, and so moves HEAD to 12th commit
// run your test again

git bisect run [command-with-args]

~/.gitconfig
git config --global color.ui true
git config --global color.status auto
git config --global color.branch auto

http://prismoskills.appspot.com/lessons/Git/Chapter_10_-_Operators.jsp
.. operator
git log branch1..branch2 (shows logs from commits present in branch2 but not in branch1)
git log origin/master..HEAD (shows what you are about to push to origin/master from HEAD)
... operator
git log branch1...branch2 will show commits present in branch1 OR branch2 but not in both.
It can be combined with --left-right operator to show which commit belongs to which branch.
git log --left--right branch1...branch2

--not operator and ^ operator used as negation
^ operator can also be used as a negation operator in which case it becomes equivalent to the --not operator.
For example: the following commands are same:
git log branch1..branch2
git log ^branch1 branch2
git log branch2 --not branch1

This becomes useful when operating on multiple branches.
For example: the following commands are same:
git log branch1 branch2 ^branch3
git log branch2 branch2 --not branch3

Git show (blobs, trees, tags and commits)
http://prismoskills.appspot.com/lessons/Git/Chapter_09_-_Git_show.jsp
git show can be used to show information on blobs, trees, tags and commits.

git show HEAD^ shows information about parent of HEAD.
git show HEAD^3 shows information about third parent of HEAD.
git show HEAD~ shows information about parent of HEAD (same as HEAD^).
git show HEAD~3 shows information about "first parent of first parent of HEAD". This can also be written as HEAD^^^
To create a new branch and switch to it at the same time, use the command:
git checkout -b [branch-name]

Git creates a branch just by storing a pointer to the parent branch's snapshot.
Due to this, branching in git is almost instantaneous.
This is unlike other VCSs where branching means making copies of all the files.
http://prismoskills.appspot.com/lessons/Git/Chapter_06_-_Tagging.jsp
git tag (lists all the tags)
git tag -l 'release-*' (allows you to filter tags matching release-*)
git tag -a <tag-name> (creates a tag. -a instructs git to store tagger's information like email, name, date etc)
git show <tag-name> (shows all the information about a tag)

You can also create tags for previous commits.
To do this, find out the checksum of the previous commit using git log --pretty=online
Then tag it normally, but specify the checksum.
Example:
git tag -a 'tag for alpha release' -m 'forgot to create tag' fga878fsdjhfd0fhd8 (The last argument is the checksum)

Tags are not pushed to remote servers by default.
To do that, use the following 2 commands:
git push <remote-name> <tag-name> (pushes the specified tag)
git push <remote-name> --tags (pushes all the tags)
Remote repositories in Git
To add a remote repository to your local, execute the following command:
git remote add [logical-name] [URL]

The above only adds a pointer to the remote repository, does not fetch it.
To fetch a remote, use:
git fetch [logical-name] (This gets all the files for this remote to your local area)
When a repository is cloned, git automatically adds a logical-name of origin to it.
So if you do git fetch origin, you will get all the changes since you cloned/last-fetched.

Important: fetch command does not do any automatic merge.
Opposite to this behavior is the git pull command which fetches data and also merges it.

To push the changes to [remote-name] from [branch-name], use:
git push [remote-name] [branch-name]

To discard all changes in the local area, use:
git checkout -- <file>

Git log (Viewing File History)
git log --graph
git log --stat
git log -2 (limits the number of historical entries to 2)
git log --committer <committer>
git log --grep <pattern to grep in commit messages>
git log --pretty=oneline (shows the checksum of each commit along with the commit message)
git log --since=3.weeks
git log --after="3 minutes ago" (--until, --before can also be used)

Branches on remote repositories
Branches on remote repositories are specified as [remote-name] / [branch-name]
For example: origin repository's master branch is referred to as origin/master
If a colleague creates a branch test from the origin, then that would be referred to as origin/test

Summary:
origin/master refers to the master branch on the 'original' remote repository
Plain master refers to the master branch on the 'local' repository

It is helpful to remember that origin/master is just a pointer to the remote master set during local master creation and updated with each fetch/pull.

What is the difference between git pull origin master and git pull origin/master?

git pull origin master will pull latest master branch from origin remote and merge to current local. Simple!
git pull origin/master will merge local copy of master branch (which was brought in sync with origin remote during last git fetch) into current local.

Basically the behavior of pull is same in both the cases.
origin/master refers to local cached copy of master from origin and
origin master refers to the latest up-to-date master branch at origin.
http://prismoskills.appspot.com/lessons/Git/Chapter_11_-_Git_stash.jsp
git stash helps you save uncommitted work onto a stack and cleans the directory by doing away with the uncommitted work.
Multiple stash commands form a stack of uncommitted work items.

git stash list shows you the stack of these items.
git stash apply stash@{number} can be used to apply the diffs from stash#2 on the current repository.
git stash drop stash@{number} deletes the specified stash.
git stash branch [temp-branch-name] creates a new branch before applying changes in the stash.
Useful when conflicts are expected.

Reset or revert a specific file to a specific revision using Git?
git checkout abcde file/to/restore

http://blog.94fzb.com/post/177
git 提交了一些敏感信息,如何进行彻底删除
如果自己一个不小心的提交了一些敏感的信息到git 上面,

而自己的项目有可能被其他人看到,如果查看历史记录还是能看到自己提交那些文件。那么如果彻底从历史记录中的删除这些文件 操作是在 Linux下面做的
git filter-branch --index-filter 'git rm --cached --ignore-unmatch db.properties*' --prune-empty --tag-name-filter cat -- --all
git push origin master --force 
rm -rf .git/refs/original/  
git reflog expire --expire=now --all  
git gc --prune=now  
git gc --aggressive --prune=now

Git 提交的正确姿势:Commit message 编写指南
http://www.oschina.net/news/69705/git-commit-message-and-changelog-guide

<
type>(<scope>): <subject>// 空一行<body>// 空一行<footer>
其中,Header 是必需的,Body 和 Footer 可以省略。
不管是哪一个部分,任何一行都不得超过72个字符(或100个字符)。这是为了避免自动换行影响美观。
http://stackoverflow.com/questions/1783405/checkout-remote-git-branch
Checkout remote Git branch
you can just do: git fetch
git checkout test
This will fetch all of the remote branches for you. You can see the branches available for checkout with:
git branch -v -a

git commit messages
node projects:
https://blog.coding.net/blog/commit_message_change_log

http://www.ruanyifeng.com/blog/2015/12/git-workflow.html
Git Flow:
它最主要的特点有两个。
首先,项目存在两个长期分支。
  • 主分支master
  • 开发分支develop
前者用于存放对外发布的版本,任何时候在这个分支拿到的,都是稳定的分布版;后者用于日常开发,存放最新的开发版。
其次,项目存在三种短期分支。
  • 功能分支(feature branch)
  • 补丁分支(hotfix branch)
  • 预发分支(release branch)
一旦完成开发,它们就会被合并进developmaster,然后被删除。
Git flow 的详细介绍,请阅读我翻译的中文版《Git 分支管理策略》

Git flow的优点是清晰可控,缺点是相对复杂,需要同时维护两个长期分支。大多数工具都将master当作默认分支,可是开发是在develop分支进行的,这导致经常要切换分支,非常烦人。
更大问题在于,这个模式是基于"版本发布"的,目标是一段时间以后产出一个新版本。但是,很多网站项目是"持续发布",代码一有变动,就部署一次。这时,master分支和develop分支的差别不大,没必要维护两个长期分支。
三、Github flow
第一步:根据需求,从master拉出新分支,不区分功能分支或补丁分支。
第二步:新分支开发完成后,或者需要讨论的时候,就向master发起一个pull request(简称PR)。
第三步:Pull Request既是一个通知,让别人注意到你的请求,又是一种对话机制,大家一起评审和讨论你的代码。对话过程中,你还可以不断提交代码。
第四步:你的Pull Request被接受,合并进master,重新部署后,原来你拉出来的那个分支就被删除。(先部署再合并也可。)


Gitlab flow 是 Git flow 与 Github flow 的综合。它吸取了两者的优点,既有适应不同开发环境的弹性,又有单一主分支的简单和便利。它是 Gitlab.com 推荐的做法。
Gitlab flow 分成两种情况,适应不同的开发流程。
对于"持续发布"的项目,它建议在master分支以外,再建立不同的环境分支。比如,"开发环境"的分支是master,"预发环境"的分支是pre-production,"生产环境"的分支是production
开发分支是预发分支的"上游",预发分支又是生产分支的"上游"。代码的变化,必须由"上游"向"下游"发展。比如,生产环境出现了bug,这时就要新建一个功能分支,先把它合并到master,确认没有问题,再cherry-pickpre-production,这一步也没有问题,才进入production
只有紧急情况,才允许跳过上游,直接合并到下游分支。

4.3 版本发布

对于"版本发布"的项目,建议的做法是每一个稳定版本,都要从master分支拉出一个分支,比如2-3-stable2-4-stable等等。
以后,只有修补bug,才允许将代码合并到这些分支,并且此时要更新小版本号。


Github 和 Gitlab 都提供"保护分支"(Protected branch)这个功能。

5.5 Squash 多个commit

为了便于他人阅读你的提交,也便于cherry-pick或撤销代码变化,在发起Pull Request之前,应该把多个commit合并成一个。(前提是,该分支只有你一个人开发,且没有跟master合并过。)

Issue 用于 Bug追踪和需求管理。建议先新建 Issue,再新建对应的功能分支。功能分支总是为了解决一个或多个 Issue。
功能分支的名称,可以与issue的名字保持一致,并且以issue的编号起首,比如"15-require-a-password-to-change-it"。
开发完成后,在提交说明里面,可以写上"fixes #14"或者"closes #67"。Github规定,只要commit message里面有下面这些动词 + 编号,就会关闭对应的issue。
  • close
  • closes
  • closed
  • fix
  • fixes
  • fixed
  • resolve
  • resolves
  • resolved
http://gitready.com/beginner/2009/01/18/the-staging-area.html
Using the index is quite simple with the git add and git commit commands. Basically, you add files onto the index, and once you’re satisfied with the changescommit them
http://gitolite.com/uses-of-index.html
The index (or any of its other names) is essentially a "holding area" for changes that will be committed when you next do git commit. That is, unlike other VCSs, a "commit" operation does not simply take the current working tree and check it as-is into the repository. The index allows you to control what parts of the working tree go into the repository on the next "commit" operation.

1. 修改错误的提交信息(commit message)

提交信息很长时间内会一直保留在你的代码库(code base)中,所以你肯定希望通过这个信息正确地了解代码修改情况。 下面这个命令可以让你编辑最近一次的提交信息,但是你必须确保没有对当前的代码库(working copy)做修改,否则这些修改也会随之一起提交。
$ git commit --amend -m ”YOUR-NEW-COMMIT-MESSAGE”
假如你已经将代码提交(git commit)推送(git push)到了远程分支,那么你需要通过下面的命令强制推送这次的代码提交。
$ git push <remote> <branch> --force

2. 提交之前撤销git add

如果你往暂存区(staging area)中加入了一些错误的文件,但是还没有提交代码。你可以使用一条简单的命令就可以撤销。如果只需要移除一个文件,那么请输入:
$ git reset <文件名>
或者如果你想从暂存区移除所有没有提交的修改:
$ git reset

3. 撤销最近一次代码提交

有时候你可能会不小心提交了错误的文件或一开始就遗漏了某些东西。下面这三步操作可以帮助你解决这个问题。
$ git reset --soft HEAD~1
# 对工作文件进行必要的更改
$ git add -A .
$ git commit -c ORIG_HEAD
你执行第一个命令时,Git会将HEAD指针(pointer)后移到此前的一次提交,之后你才能移动文件或作必要的修改。
然后你就可以添加所有的修改,而且当你执行最后的命令时,Git会打开你的默认文本编辑器,其中会包含上一次提交时的信息。如果愿意的话,你可以修改提交信息,或者你也可以在最后的命令中使用-C而不是-c,来跳过这一步。

7. 删除本地和远程Git分支

删除本地分支:
$ git branch --delete --force <branchName>

或者使用选项-D作为简写:

$ git branch -D
删除远程分支:
$ git push origin --delete <branchName>

https://github.com/kaiye/kaiye.github.com/issues/7
git remote add origin <git仓库地址>
2、查看 origin 仓库信息

# 以下三种方式均可
git config get --remote.origin.url
git remote -v
git remote show origin

3、删除 origin 仓库信息
git remote rm origin

问:如何撤销修改?

修改包含四种情况,需单独区分。

1、新建的文件和目录,且从未提交至版本库

此类文件的状态为 Untracked files ,撤销方法如下:

git clean -fd .
其中,. 表示当前目录及所有子目录中的文件,也可以直接指定对应的文件路径,以下其他情况类似。

2、提交过版本库,但未提交至暂存区的文件(未执行 git add)

此类文件的状态为 Changes not staged for commit,撤销方法:

git checkout .
3、已提交至暂存区的文件

此类文件的状态为 Changes to be committed,撤销方法:

git reset .
执行之后文件将会回到以上的 1 或者 2 状态,可继续按以上步骤执行撤销,若 git reset 同时加上 --hard 参数,将会把修改过的文件也还原成版本库中的版本。

4、已提交至版本库(执行了 git commit)

每次提交都会生成一个 hash 版本号,通过以下命令可查阅版本号并将其回滚:

git log
git reset <版本号>
如果需要「回滚至上一次提交」,可直接使用以下命令:

git reset head~1
执行之后,再按照 1 或者 2 状态进行处理即可,如果回滚之后的代码同时需要提交至 origin 仓库(即回滚 origin 线上仓库的代码),需要使用 -f 强制提交参数,且当前用户需要具备「强制提交的权限」。

5、如果回滚了之后又不想回滚了怎么办?

如果是以上的情况 1 或者 2,只能歇屁了,因为修改没入过版本库,无法回滚。

如果是情况 4,回滚之后通过 git log 将看不到回滚之前的版本号,但可通过 git reflog 命令(所有使用过的版本号)找到回滚之前的版本号,然后 git reset <版本号> 。

问:遇到冲突了怎么解决?

两个分支进行合并时(通常是 git pull 时),可能会遇到冲突,同时被修改的文件会进入 Unmerged 状态,需要解决冲突。

1、最快的办法

大部分时候,「最快解决冲突」的办法是:使用当前 HEAD 的版本(ours),或使用合并进来的分支版本(theirs)。

# 使用当前分支 HEAD 版本,通常是冲突源文件的 <<<<<<< 标记部分,======= 的上方
git checkout --ours <文件名>

# 使用合并分支版本,通常是源冲突文件的 >>>>>>> 标记部分
git checkout --theirs <文件名>

# 标记为解决状态加入暂存区
git add <文件名>
2、最通用的办法

用编辑器打开冲突的源文件进行修改,可能会发生遗留,且体验不好,通常需要借助 git mergetool 命令。

在 Mac 系统下,运行 git mergetool <文件名> 可以开启配置的第三方工具进行 merge,默认的是 FileMerge 应用程序,还可以配置成 Meld 或 kdiff3,体验更佳。

3、最好的习惯

有三个好的习惯,可以减少代码的冲突:

在开始修改代码前先 git pull 一下;
将业务代码进行划分,尽量不要多个人在同一时间段修改同一文件;
通过 Gitflow 工作流 也可以提升 git 流程效率,减少发生冲突的可能性。

设置本地分支与远程分支保持同步,在第一次 git push 的时候带上 -u 参数即可

git push origin master -u
# 列出所有本地 tag
git tag  

# 本地新增一个 tag,推送至 origin 服务器
git tag -a v1.0.0 -m 'tag description'
git push origin v1.0.0

# 删除本地与 origin tag
git tag -d v1.0.0
git push origin --delete v1.0.0
使用 git GUI 客户端(如,SoureTree、Github Desktop)能极大的提升分支管理效率。分支合并操作通常只有两种情况:从 origin merge 到本地,使用 git pull 即可;从另外一个本地分支 merge 到当前分支,使用 git merge <分支名>,以下是常用命令:

# 新建分支 branch1,并切换过去
git checkout -b branch1

# 查看所有本地与远程分支
git branch -a

# 修改完成后,切换回 master 分支,将 branch1 分支合并进来
git checkout master
git merge branch1

# 删除已完成合并的分支 branch1
git branch -d branch1

问:如何在 git log 中查看修改的文件列表?

默认的 git log 会显示较全的信息,且不包含文件列表。使用 --name-status 可以看到修改的文件列表,使用 --oneline 可以将参数简化成一行。

git log --name-status --oneline
每次手动加上参数很麻烦,可以通过自定义快捷命令的方式来简化操作:

git config --global alias.ls 'log --name-status --oneline --graph'
运行以上配置后,可通过 git ls 命令来实现「自定义 git log」效果,通过该方法也可以创建 git st 、 git ci 等一系列命令,以便沿用 svn 命令行习惯。

git config --global alias.st 'status --porcelain'
更多 git log 参数,可通过 git help log 查看手册。

如果是看上一次提交的版本日志,直接运行 git show 即可。

问:如何在不提交修改的前提下,执行 pull / merge 等操作?

有些修改没有完全完成之前,可能不需要提交到版本库,圡方法是将修改的文件 copy 到 git 仓库之外的目录临时存放,pull / merge 操作完成之后,再 copy 回来。

这样的做法一个是效率不高,另外一个可能会遗漏潜在的冲突。此类需求最好是通过 git stash 命令来完成,它可以将当前工作状态(WIP,work in progress)临时存放在 stash 队列中,待操作完成后再从 stash 队列中重新应用这些修改。

以下是 git stash 常用命令:

# 查看 stash 队列中已暂存了多少 WIP
git stash list

# 恢复上一次的 WIP 状态,并从队列中移除
git stash pop

# 添加当前 WIP,注意:未提交到版本库的文件会自动忽略,只要不运行 git clean -fd . 就不会丢失
git stash

# 恢复指定编号的 WIP,同时从队列中移除
git stash pop stash@{num}

# 恢复指定编号的 WIP,但不从队列中移除
git stash apply stash@{num}


Labels

Review (572) System Design (334) System Design - Review (198) Java (189) Coding (75) Interview-System Design (65) Interview (63) Book Notes (59) Coding - Review (59) to-do (45) Linux (43) Knowledge (39) Interview-Java (35) Knowledge - Review (32) Database (31) Design Patterns (31) Big Data (29) Product Architecture (28) MultiThread (27) Soft Skills (27) Concurrency (26) Cracking Code Interview (26) Miscs (25) Distributed (24) OOD Design (24) Google (23) Career (22) Interview - Review (21) Java - Code (21) Operating System (21) Interview Q&A (20) System Design - Practice (20) Tips (19) Algorithm (17) Company - Facebook (17) Security (17) How to Ace Interview (16) Brain Teaser (14) Linux - Shell (14) Redis (14) Testing (14) Tools (14) Code Quality (13) Search (13) Spark (13) Spring (13) Company - LinkedIn (12) How to (12) Interview-Database (12) Interview-Operating System (12) Solr (12) Architecture Principles (11) Resource (10) Amazon (9) Cache (9) Git (9) Interview - MultiThread (9) Scalability (9) Trouble Shooting (9) Web Dev (9) Architecture Model (8) Better Programmer (8) Cassandra (8) Company - Uber (8) Java67 (8) Math (8) OO Design principles (8) SOLID (8) Design (7) Interview Corner (7) JVM (7) Java Basics (7) Kafka (7) Mac (7) Machine Learning (7) NoSQL (7) C++ (6) Chrome (6) File System (6) Highscalability (6) How to Better (6) Network (6) Restful (6) CareerCup (5) Code Review (5) Hash (5) How to Interview (5) JDK Source Code (5) JavaScript (5) Leetcode (5) Must Known (5) Python (5)

Popular Posts