1. Command

1.1. add

git add [--verbose | -v] [--dry-run | -n] [--force | -f] [--interactive | -i] [--patch | -p]
        [--edit | -e] [--[no-]all | --[no-]ignore-removal | [--update | -u]]
        [--intent-to-add | -N] [--refresh] [--ignore-errors] [--ignore-missing] [--renormalize]
        [--chmod=(+|-)x] [--] [<pathspec>…​]

2. 'gitignore'

A gitignore file specifies intentionally untracked files that Git should ignore. Files already tracked by Git are not affected.

Each line in a gitignore file specifies a pattern.

2.1. Pattern Format

  • A blank line matches no files, so it can serve as a separator for readability.
  • If the pattern ends with a slash, it would only find a match with a directory. In other words, foo/ will match a directory foo and paths underneath it, but will not match a regular file or a symbolic link foo (this is consistent with the way how pathspec works in general in Git).
  • If the pattern does not contain a slash /, Git treats it as a shell glob pattern and checks for a match against the pathname relative to the location of the .gitignore file (relative to the toplevel of the work tree if not from a .gitignore file).
  • A leading slash matches the beginning of the pathname. For example, /*.c matches cat-file.c but not mozilla-sha1/sha1.c.

Two consecutive asterisks (**) in patterns matched against full pathname may have special meaning:

  • A leading ** followed by a slash means match in all directories. For example, **/foo matches file or directory foo anywhere, the same as pattern foo. **/foo/bar matches file or directory bar anywhere that is directly under directory foo.
  • A trailing /** matches everything inside. For example, abc/** matches all files inside directory abc, relative to the location of the .gitignore file, with infinite depth.
  • A slash followed by two consecutive asterisks then a slash matches zero or more directories. For example, a/**/b matches a/b, a/x/b, a/x/y/b and so on.

2.2. Example

$ git status
# Untracked files:
#       Documentation/foo.html
#       Documentation/gitignore.html
#       file.o
#       lib.a
#       src/internal.o
$ cat .git/info/exclude
# ignore objects and archives, anywhere in the tree.
$ cat Documentation/.gitignore
# ignore generated html files,
# except foo.html which is maintained by hand
$ git status
# Untracked files:
#       Documentation/foo.html

3. 「如何优雅地在 Github 上贡献代码」

swoole 为例:

  1. Fork 项目并 Clone 到本地

  2. 获取原项目代码

    1. 进入 swoole-src 文件夹,添加 swoole 的远程地址

      git remote add upstream
    2. 获取 swoole 最新源码

      git pull upstream master

    现在我们在 fork 来的 master 分支上,这个 master 留作跟踪 upstream 的远程代码

  3. 创建分支

    按照国际惯例,我们一般不在 master 上提交新代码,而需要为新增的功能或者 fixbug 建立新分支,再合并到 master 上

    1. 创建分支

      git checkout -b branch1
    2. 提交到代码库

      git commit -a -m "new commit"
  4. 合并修改

    一个常见的问题是远程的 upstream (swoole/swoole-src) 有了新的更新,从而会导致我们提交的 Pull Request 时会导致冲突,因此我们可以在提交前先把远程其他开发者的 commit 和我们的 commit 合并

    1. 切换到 master 分支

      git checkout master
    2. 拉出远程的最新代码

      git pull upstream master
    3. 切换回 branch1

      git checkout branch1
    4. 把 master 的 commit 合并到 branch1

      git rebase master
    5. 把更新代码提交到自己的 branch1 中

      git push origin branch1
  5. Pull Request

    你可以在你的 github 代码仓库页面切换到 branches 页面点击 branch1 分支后点击 New pull request 按钮,添加相关注释后提交

    或者切换到 branch1 分支的代码仓库点击 Compare & pull request 按钮,添加相关注释后提交