description: > Various git recipes for everyday use. From moving commits to OS contributions via Github.
Note: All aliases are listed on this gitconfig file{:rel="nofollow noreferrer noopener"}
Table of Contents
Since the diff already shows what changed,
Assumptions:
master
is the release/production branchorigin
is the centralized repo we ownupstream
is the centralized repo we contribute to$ git take feature-branch
# work, and commit
# update branch frequently
$ git down origin/master
# release new feature
$ git go master
$ git merge feature-branch
$ git delete feature-branch
$ git onup
To update feature-branch
with master
changes
$ git rebase master
To keep feature-branch
history as part of master avoid squash
, and
fast-forward
.
Only rewrite history in local branches which have not been shared with anyone.
By design, we can contribute to any repo even when we don't have access
to the centralized repo. Most git web services allow to clone repos using
the git://
protocol
$ git clone git://url-to-centralized/repo
Once we are ready to send our changes back to the maintainer
$ git format-patch master --output-dir ./patch
We can also generate patches for a range of commits.
$ git format-patch --output-dir ./patch HEAD~..HEAD
If we worked on a new branch we might need to rebase
before generating
a patch to prevent exceptions.
$ git down upstream/master
By default, git creates a patch file per commit. To create a single file we can
$ git format-patch master --stdout > new-feature.patch
We can do a test run to check what we are sending
$ git send-email patch/* --subject='Fix, New feature, etc' --to='maintainer@floss-project.org' --dry-run
Finally, we can send our patches adding a message
$ git send-email patch/* --compose --subject='Fix, New feature, etc' --to='maintainer@floss-project.org' --quiet
It's considered best practice to
best practice | flag |
---|---|
Request comments | --rfc |
Send multiple files | --numbered |
Detect renames | --find-renames |
Only use --find-renames
when we know the maintainers patch via git
.
Checkout the docs for details on how to configure send-email{:rel="nofollow noreferrer noopener"}, and format-patch{:rel="nofollow noreferrer noopener"}.
When we receive a patch is better to review it in a feature branch.
$ git checkout review-new-feature
When we receive the patch as a single file we can
$ cat new-feature.patch | git am
For multiple files we can simply
$ cat *.patch | git am
We can verify we've applied the patch correctly with
$ git log --oneline
Beware, the SHA of the patch applied is different from the SHA of the patch sent. Yet, the messages should be left unchanged.
aka pull request
upstream
.$ git remote -v # list all remote repos
$ git remote add upstream https://github.com/ORIGINAL_OWNER/REPO.git
origin
When debuggin focus on how the code got to its current state. To show
the full history of some_code
across multiple commits and files use:
$ git log -S "some_code"
Use --patch
to include the full diff, and --reverse
to show when it
was added at the top.
n
commits to existing branchUncommitted work will get lost.
$ git log-recent
$ git go existing-branch
$ git merge master
$ git go master
$ git undo-for-good HEAD~n
$ git go existing-branch
Alternatively, to move the last commit we can
git uncommit
git stash
git go correct-branch
git stash pop
git add --all # or add individually
n
commits to new branchUncommitted work will get lost.
$ git log-recent
$ git branch new-branch
$ git undo-for-good a1b2c3d4
$ git go new-branch
From time to time we need to create an empty commit to trigger the CI pipeline
$ git commit --allow-empty --message "Trigger CI pipeline"
We can also use this technique to init
an empty repo. Which allows us
to rebase the first commit.
Git allows pushing to multiple remote repos. Assuming we've already set
origin
add origin once more, as well as all mirrors:
$ git remote set-url --add --push origin git@<main-remote.org>:<username>/<repo>.git
$ git remote set-url --add --push origin git@<mirror-remote.com>:<username>/<repo>.git
Verify push settings:
$ git remote -v
Beware that we can only pull
from main-remote
origin repo. To get
changes from all mirrors:
$ git fetch --all
Whenever we want to switch from one git service provider to another we simply need to do:
$ cd <existing_repo>
$ git remote rename origin old-origin
$ git remote add origin git@<new-upstream.com>:<username>/<repo>.git
$ git push -u origin master
If we want to include all branches, and tags:
$ git push -u origin --all
$ git push -u origin --tags
To delete old-origin
branches, and configuration settings:
$ git remote remove old-origin