git Notes - ipatch/dotfiles GitHub Wiki
- Gotchas
- Working with remote branches
- GitHub Notes
- Working with other repos
- GitHub Useful Links
- git Submodules
- git rebase
- git reset
- git clone
- git merge
- git branch
- git pull
- git push
- git stash
- git tag
- git remote
- .gitignore
- Comparing two different git branches
-
Working with
git-crypt
- git GPG
- Working with git hooks
- Working with Identities
- git Troubleshooting
- Unsorted
- Useful Links
- TODOs
Gotchas π¬ π
Git allows me to track multiple remote forks in a single git repo which is helpful for containing different branches of different forks of a single project within a single local dir / git repo. However there are some caveats when setting up a project this way. These notes should not be taken as gospel but rather considered a reasonable practice, and not even considered a best practice, for the fact that I haven't extensively use git for such means.
For my particular use case, I forked the Marlin Firmware for a GitHub to work on my local changes of the Marlin source for my specific 3d printer. I setup my fork to be the origin of the marlin fork, and set the upstream to be the official Marlin repo, so that I can pull in upstream changes from the official marlin repo at my leasure, while maintaining my local changes and not creating an entire mess of the project. That said, InsanityAutomation maintains an active fork of the Marlin repo specific to Creality printers, which I would also like to checkout branches and experiment with features from his / her fork. I might have forked and cloned InsanityAutomation's fork of Marlin as well within a completely separate local directory on my box, and that seems like a code smell for maintaining separate local directories of essentially the same proect, so instead forking forks and forgetting what is exactly where, since IA forked the same git project as myself, and I setup my local fork of Marlin to track his fork of Marlin, so I only have one directory on my box containing the Marlin source, but have setup multiple remotes tracking multiple forks of the Marlin firmware.
To list all remotes can be considered remote git projects that are forked from the Marlin source.
git remotes
InsanityAutomation https://github.com/InsanityAutomation/Marlin (fetch)
InsanityAutomation https://github.com/InsanityAutomation/Marlin (push)
origin https://github.com/ipatch/Marlin.git (fetch)
origin https://github.com/ipatch/Marlin.git (push)
upstream https://github.com/MarlinFirmware/Marlin (fetch)
upstream https://github.com/MarlinFirmware/Marlin (push)
The remotes can be modified with the git subcommands
git remote add [NAME OF REMOTE] [https://github.com/[USER]/[PROJECT].git]
echo "example"
git remote add origin https://github.com/ipatch/Marlin.git
If a remote needs to be updated
git remote set-url [NAME OF REMOTE] [UPDATED URL]
βοΈ Even though the local git fork is setup to track a remote, such as for my case, my local fork of Marlin is tracking the official git repo / project, I'm also tracking the InsanityAutomation fork of Marlin, thus the multiple remotes, and with out fetching the objects (using that term very loosely here), I will not be able to checkout any of the branches specific to the IA fork of marlin, to checkout a remote fork's branch, first fetch the remotes objects
git fetch [NAME OF REMOTE]
echo "my use case"
git fetch InsanityAutomation
After fetching the objects (I'm considering these to the IA specific branches of the Marlin project). I can fetch a branch specific to the IA fork of Marlin.
git branch --all
git checkout [NAME OF REMOTE/NAME OF BRANCH]
echo "my use case"
git checkout --track InsanityAutomation/CrealityDwin2.0_Bleeding
I've had mixed results with using
git checkout --track
for pulling in a new upstream branch into a local fork of an upstream project, the below command may also work if issues arise with the above methods
git fetch upstream
git fetch upstream [BRANCH_NAME]
git remote set-branches --add [NAME_OF_REMOTE] [BRANCH_NAME]
echo "verify remote branch exists in local fork/repo"
git branch --all
βοΈ I'd highly suggest creating a local branch from the freshly checked out branch so things do not become an entire mess in the future.
To download a single directory folder or directory from GitHub the easiest solution I've found is to use svn checkout
svn checkout https://github.com/ipatch/dotfiles/trunk/install
git
can not expand SHELL environment variables stored in the .gitconfig
, ie. $HOME
will not be expanded in .gitconfig
.
When creating folders / directories within a git repo remember there must be a file placed within the directory ie. a .gitkeep
file in order for git to start tracking the directory.
To remove files from local & remote git repositories
git rm --cached /path/to/mr-fancy-pants
Make sure to add /path/to/mr-fancy-pants to
.gitignore
after removing the cached files.
Gotchas working with remote branches π
π¨ make sure there is a tracking information setup for the branch if trying to fetch remote counterparts without merging them, ie. git remote update
will not print any warnings or errors when run on a local branch without a remote counterpart. true story
To setup a remote tracking branch for the local working branch for a git project
git branch --set-upstream-to=origin/[mr-fancy-branch] [mr-fancy-local-branch]
local branches generally have the same name as their remote counterparts.
GitHub Notes π
To find the date of the first commit for a GitHub repo divide the total number of commits by thirty five 35, ie. (the number of commits displayed per page when viewing the commit history for a project on GitHub).
Ex
2600 / 35 ~= 74.2...
Round 74.2 up to 75 and the first commit for a project will be displayed on the 75th page of the git repo.
https://github.com/mr-fancy-42/repo/master?page=75
To view the history / log of a GitHub wiki
https://github.com/[USER]/[REPO]/wiki/_history
https://github.com/mr-fancy-user/42/wiki/_history
To test and make sure OpenSSH is working properly with GitHub
ssh -T [email protected]
should output the below,
Hi ipatch! You've successfully authenticated, but GitHub does not provide shell access.
To search for a particular file on GitHub.com
βtmux.confβ in:path
Working with other repos π
If local fork of a project, ie. my fork of asdf
is several commits behind the upstream counterpart, upstream commits can be merged into the master branch of the local fork.
- Fetch the upstream changes
git fetch upstream master
The above git command will not merge remote changes into local fork.
To merge remote changes into local fork's master branch
git pull upstream master
- Switch to local fork's master branch
git checkout master
- Merge upstream changes into local fork's master branch
git merge upstream/master
To push remote changes merged into local fork from running prior git
commands
git push origin master
GitHub Useful Links π
- performing searches on GitHub.com
- hub
- GitHub - Creating project pages
- GitHub Syncing a fork
- StackOverflow push remote changes to local fork
- Viewing a GitHub's wiki history
git rebse π
git rebase
is useful for working on a forked project from GitHub, and one wants to condence all their local / remote commits to one substantial commit for easy PR's to the maintainers of the main repo of the locally forked project.

git rebase Use case π
You have forked a project on GitHub, and your project is ~ 35 commits ahead of it's forked counterpart. You want to squash all local 35 commits into one.
To start an interactive rebase session.
git rebase -i
The above command will open up the $EDITOR
and each commit can be marked with a one letter value described in the editor session, ie. s
for squash commit.
If the ~ 35 commits have been pushed to GitHub one can push the rebase to a remote repo if no one else is working with the remote repo.
To force push a rebase to GitHub
git push origin +master
If the interactive rebase encouters issues, one will have to handle merge conflicts, usually by running git add --all
and then running git rebase --continue
to continue with the rebase.
To change the commit message after rebasing
git commit --amend -m "my fancy ammended commit"
To overwrite all local changes with those of the upstream master branch
git pull --rebase upstream master
git rebase Troubleshooting π
To abort a rebase
git rebase --abort
To switch / checkout or rollback / revert a paritcular branch / tag / commit
git reset --hard [tag|branch|commit ID]
git Submodules π
To pull the latest changes from a remote repository for a submodule
git submodule update --recursive --remote
git pull --recurse-submodules # or
git pull upstream master --recurse-submodules # or
git submodule foreach git pull origin master # or
When cloning a git repo that contains submodules, the submodule git repos will always clone with
detached HEAD
. see this
To add a .wiki
GitHub repo as submodule to the parent repo
git submodule add https://github.com/ipatch/theairportwiki.wiki.git .wiki
To remove a link related to a submodule
git ls-files --stage | grep 160000
Output will look something similar to,
160000 e2b695b0432a600ff6d023ed4c9b9f3516673c7f 0 config/base16-shell
160000 911459645f76c7fb977520beddec2d552117e7b2 0 config/config/base16-shell
git rm --cached config/config/base16-shell
To push all git repos including submodules with staged commits
git push --recurse-submodules=on-demand
Troubleshooting git submodules π
If you run into the below error when working git submodules
mr-fancy-42-repo already exists in the index
- Remove the submodule folder / directory
- Remove the git cache for the folder / directory
- Then reinitialize submodule
rm -rf /path/to/mr-fancy-42-repo
git rm -r /path/to/mr-fancy-42-repo
git submodule add [mr-fancy-42-submodule-repo] /path/to/initialize/submodule/repo
git clone π
β οΈ When performing a git clone git defaults to cloning all meta data related to the master branch.
To clone a repository with a specified history use the --depth
flag, ie. 50 specifies the last number of commits to be cloned into the local git repo.
git clone --depth 50 [email protected]:ipatch/dotfiles.git
To clone a specific branch from a particular repo
git clone -b [branch-name] [remote-repo.git]
To clone repo submodules after a repo has already been cloned.
git submodule update --init --recursive
To clone a repo and all included submodules in the repo
git clone --recurse-submodules https://tld.com/username/repo.git
A git repository can be cloned with a depth of 1 which can be considered a shallow clone of a repo, which will not expose the remote repo branches to the locally cloned repo. That said, there is a bit of a work around to fetch and checkout out a remote branch that does exist locally.
Example
git clone --depth=1 https://github.com/ipatch/KegCop
git config remote.origin.fetch +refs/heads/\*:refs/remotes/origin/\*
git fetch --unshallow
git co dev
An alternative to the above method of checking out remote branches on a locally shallowed cloned repo
git clone --depth=1 https://github.com/ipatch/KegCop --no-single branch
git checkout can be used to selectively upgrade a file or a hunk of files from one branch to another.
Example
Some updates were applied to a directory of files on the master branch and one wants to update a branch with only files from a specific directory that were changed on the master branch.
git checkout branch-that-needs-updating
git checkout master -- [./path/to/hunk/dir/of/files]
Files can be selectively updated interactively if preferred.
git checkout branch-that-needs-updating
git checkout -p master -- [./path/to/hunk/dir/of/files]
To undo the applied changes
git reset [./path/to/hunk/dir/files]
git clean π
To clean artifacts when configuring and building projects from within the git project root
git clean
The above command is useful for cleaning artifacts from running the below commands
./configure
make
git rm π
To remove a file from a git repository, and stop tracking the file with git
git rm mr-fancy-file.txt
You have accidently pushed local files to a remote repository, and now you do not want the files on the remote repository
git rm --cached -r .
The above command will remove all cached files in the working directory.
β οΈ Remember to update the.gitignore
for the repo to reflect the new changes.
git merge π
To merge in a single file from a remote counterpart from a different branch or even a different remote, ie. upstream
git fetch
git checkout upstream/master [path/to/file]
To continue a merge after fixes have been applied because an automerge / auto merge failed for whatever reason.
git merge --continue
To merge in a single file from a development branch into master.
git checkout master
git checkout --patch dev-branch ./path/to/file
If ./path/to/file does not exist omit the
--patch
flag
To merge two git repos with unrelated histories
git merge --allow-unrelated-histories
To resolve changes that can not be auto merged, use the_platinum_searcher along with fish and sed to search for certain patterns within the Formula
directory
ie. to remove all lines where the first char begins with =
and ends with =
for i in *.rb
sed -i -e 's/^==$//g' $i
end
ie. to remove all lines that start with >>>>>>> [followed-by-a-41-char-hash]
for i in *.rb
sed -i -e 's/>>>>>>>.*//g' $i
end
ie. to remove all occurences of <<<<<<< HEAD
for i in *.rb
sed -i -e 's/<<<<<<< HEAD//g' $i
end
git branch π
To create a new branch and switch to it after creating it with one command to rule them all
git checkout -b "mr-fancy-pants-branch"
To get a list of remote branches for the current git repo / project
git branch -r
As of June 26 2018, I don't think git provides a facility to checkout all remote branches from a remote repo. π€· That said, the below two commands pair well π· π§ with each other.
git branch --all
git checkout "mr-fancy-42-remote-branch"
To list all branches of a git repository
git branch -a
To checkout a remote branch that presently isn't available locally
git co mr-fancy-42-branch/develop
To delete a local git branch
git branch -d mr-fancy-pants
To delete a remote branch
git push origin --delete mr-fancy-pants
To push a locally created branch to its remote counterpart
git push -u origin [mr-fancy-branch]
To rename a branch locally and remotely
git branch -m [old-branch-name] [new-branch-name]
git branch Advanced Usage π π
To remove a reference from a local repo to a remote branch that no longer exists
git fetch --prune
The above command will update local refs to remote counterparts
To delete all local tracking branches that don't exist on the remote
git branch -r | awk '{print $1}' | egrep -v -f /dev/fd/0 <(git branch -vv | grep origin) | awk '{print $1}' | xargs git branch -d
The above command will need to be run bash
git branch rename workflow π
- rename the branch locally
- push new branch name to remote repository
- delete old-branch locally
- delete old-branch remotely
git branch shallow clone π
When working with a shallow clone of a git repo, remote branches can not be checked out using standard methods. The procedure for checking out a remote branch from a shallow clone is as follows.
git clone --depth 1 [email protected]:user/repo.git
git remote set-branches origin 'remote_branch_name'
git fetch --depth 1 origin remote_branch_name
git checkout remote_branch_name
git pull π
To undo a git pull
git reset --hard
To reset a repo from its upstream counterpart
git remote update
git reset --hard upstream/master --
git push π
To push a submodule repo, ie. the repo that houses this wiki π to a specific remote repo, ie. notabug.org
git push notabug.org master
The remote repo name is contingent on the name of the remote repo in the config file for the git project.
To push local changes to a remote repo and overwrite the remote changes
git push -f [remote-repo-name] [branch]
Ex
git push -f notabug.org master
-f flag force local changes to overwrite remote counterparts.
git stash π
To create a stash with a specific name
git stash save [mr-fancy-42-stash-name]
To git stash only a specific file
Requires git β₯ 2.13
git sash push -m [NAME-OF-STASH] /path/to/stashed/file
To blow up π£ local changes and overwrite with the remote counterparts
git stash --include-untracked
git pull
π¨ To remove all local entries from the local stash
git stash clear
To list all local entries in the local stash
git stash list
To apply a stash to the current branch
git stash apply
To git stash drop a specific / single stash on the git stash stack / list
fish shell requires escaping curly braces
git stash drop stash@\{42\}
If the applied stash looks good, then it can be removed with the drop command.
git stash drop
git tag π
To create a git tag for a particular commit
git tag v0.1.0
To print or show all the tags for a git repo
git tags
To push git tags to a remote repo
git push origin master --tags
To checkout and work with a specific tag release of a git repository
git checkout tags/[mr-fancy-tag-name] -b [mr-fancy-branch]
To check out all tags for a particular repo
git fetch --all --tags
To delete a tag
git tag -d [mr-fancy-tag-name]
Example
git checkout tags/v0.0.8
The above command will checkout the release v0.0.8 in a detached head state.
To verify GPG signed tag release
git tag --verify [v[MAJOR.MINOR.PATCH]]
git tag troubleshooting π
To delete a remote tag stored a git repository somewhere
git push --delete origin [mr-fancy-tag]
To delete a local tag
git tag --delete [mr-fancy-tag]
To make a tag point or reference a particular commit
git tag -a [mr-fancy-tag] [commit-hash-bdeb92d] -m "mr-fancy-tag-message-here"
To push the newly created tag to a remote repository
git push --tags origin master
To set the origin URL / remote for a git repo
Ex
git remote set-url origin [email protected]:<user_name>/<repo_name>.git
Example
git remote set-url origin [email protected]:ipatch/neomutt.git
To add an additional origin to existing git repo
git remote set-url --add origin [email protected]:truckmonth/dotfiles.git
To add an additional remote with a different name
git remote add gitlab [email protected]:truckmonth/dotfiles.git
To add an upstream repo that Pull Requests can be set to from a local fork
git remote add upstream [email protected]:GitOrg/mr_fancy_42_project.git
The above command is useful for setting up a clone to send local changes to an upstream repo.
To verify the new upstream repo has been added
git remotes
To manually modify the remotes for a git repo
- Edit
.git/config
- Look for the [remote "origin"] heading and edit accordingly.
configuring a remote fork π
.gitignore π
To see the value, ie. the file for handling USER
specific ignores
git config --list --show-origin
To set a global ignore file for a particular user
git config --global core.excludesfile "$XDG_CONFIG_HOME/git/ignore"
To get the above command to work properly on both a macOS environment and a Linux box, link the
/home
dir on macOS to the/Users
dir, and put/home/[username]/.config/git/ignore
in thegitconfig
file, and everything should be kosher β‘οΈ
Troubleshooting .gitignore π
As of git >= 1.8.2 git supports **
in a .gitignore file.
Ex
**/node_modules/*
The above line should ignore all files within a node_modules directory.
If the files are already being tracked π by git, then they will have be removed from the git cache
Ex
git rm -r --cached node_modules
macOS π
To avoid pushing the infamous π .DS_Store
files on macOS add the below line to your .gitignore
, π³
**/.DS_Store
The above line in a
.gitignore
file will recursively ignore all.DS_Store
files from a git repo or in a git project.
Working with diff
and patch
π
To apply a git diff file to the current branch of a git repo learn more
git apply mr-fancy.diff
A great π write up for working with diff
and patch
The diff command can be used to update an old file against a new file.
diff originalFile newFile > changes.patch
To update the original file
patch originalFile changes.patch
A standard install of git from a package manager on a *nix based system will more than likely provide the below visual tools for working with git.
- gitk
- git gui
An alternative to using a GUI based tool is to inspect the diff from two different branches using the below workflow
git checkout master
echo "or check brachA"
git merge --no-commit --no-ff branchB
After merging branchB into branchA it should become easy to do a git diff
and git status
to inspect the changes, if there are any.
Also if the project is hosted on GitHub then GitHub provides a web based diff tool to compare two different branches of a repo
https://github.com/[USER]/[REPO]/compare
Working with git-crypt
π
To unlock a repo using git-crypt
git-crypt unlock
To lock a repo with git-crypt
git-crypt lock
git-crypt
workflow π
- Update
.gitattributes
to include the file that you want encrypted
Ex
mr-fancy-42-secret filter=git-crypt diff=git-crypt
- Run,
git-crypt init
to update the keys for the repo, because the.gitattributes
file was updated. - Copy
mr-fancy-42-secret
file to repo, and then use standard git workflow.
git-crypt Workflow take 2 π¬ π
the git-crypt two step goes as follows,
- Obviously the working repo needs to be initialized using git-crypt with the below command.
cd /path/to/secret/sauce/git/repo
git-crypt init
- Create a
.gitattributes
file within the repo root.
touch .gitattributes
Now this is where things become highly opinionated.
- Open the
.gitattributes
file with preferred text editor.
nvim .gitattributes
- Add the below lines to the
.gitattribues
file
*.shu filter=git-crypt diff=git-crypt
From my experience the above line should recursively encrypt all files throughout the repo that have an extension with
.shu
.
-
Save and close the
.gitattribues
file. -
Add, move, copy files with
.shu
extension to repo -
Verify files are encrypted
git-crypt status | grep -i "shu"

7b. Files can be force encrypted with the below command
git-crypt status -f
The above command will print error messages if there is any issue with staging or committing the encrypted files.
- Stage, commit, push files as required
git add --all
git commit -m "??"
git push
See gotcha section if and when running into issues.
Gotchas π
If a file is created, while git-crypt has a repo in a locked state, and even if the file is white listed in the .gitattribues
to be encrypted, the file will not be encrypted when staging an "untracked" file in a git repo. From my personal experience I run into the below issue.

To get around such mentioned issue, make certain the repo isn't in a "locked state" when adding a new file that conforms to the .gitattributes
file for files being encrypted with git-crypt
. So before adding a new .shu
file to the repo make certain the repo is in an unlocked state.
git-crypt unlock
Then stage the file to be committed.
git add --all
git commit -m "add some secret sauce ?? to the repo
Optional, verify the newly added and committed file has been encrypted
git-crypt status | grep -i "shu"

The repo still should probably be in a locked state before pushing files to a public repo, so one should lock the repo. The present fish prompt I'm using will display dirty working tree even if all files have been added and committed, that said to alleviate the dirty working tree prompt, lock the repo using git-crypt.
git-crypt lock
Now one can push the encrypted files to a public git repository.
git push
Optional one can verify the files have been encrypted by trying to view the file on the public repo.

The repo will need to be placed back in an unencrypted state in order to modify / update file that has been encrypted using git-crypt because the file locally will be in an encrypted state, which can be verified by opening a encrypted file in a text editor.

To put the repo back in a state where files can be updated
git-crypt unlock
Then, update white listed encrypted files accordingly. To the best of my knowledge, the repo can remain in an unlocked state if the .gitattribues
file has not be modified, and the updates to the white listed encrypted files can be added, committed, and pushed to a public repo, and should remain encrypted on the repo, while the repo is in unlocked state locally. Thus, my reasoning for adding a .shu
extension to files that should be white listed for encryption, ie. only one rule needs to be added to the .gitattribues
file.
Homework π
- write a git hook to unencrypt
.shu
files, copy thesecrect.sause.shu
file tosecret.sause
, ie. without the.shu
extension within the same directory and add and verify thesecret.sauce
file is in the global.gitignore
file for the repo.
git GnuPG π
To restart / kickstart a gpg-agent
gpg-connect-agent reloadagent /bye
on my arch linux box i had to type in my personal access (github PAT) every time i ran git push
in order persist my credentials through reboots i settle on installing yay -S git-credential-manager-core-bin
followed by yay -S pass
. with those two utilities and properly configured .gitconfig
git with gpg should be able to persist crendentials through reboots, similiar to how macos stores credentials within its keychain(s).
see my todos in the main repo readme for links & refs to setup git-credential-manager with pass
error message / gpg #search term #searchterm
There is no assurance this key belongs to the named user
to resolve the above error message learn more
gpg --edit-key <KEY_ID>
gpg> trust
1 = I don't know or won't say
2 = I do NOT trust
3 = I trust marginally
4 = I trust fully
5 = I trust ultimately
m = back to the main menu
Your decision? 5
Do you really want to set this key to ultimate trust? (y/N) y
gpg> quit
Working with git and GnuPG π
- setup new box with existing GPG keys, in short, export existing public/private keypair scp keys to new box, import new keys
troubleshooting, search query, linux git credential-osxkeychain is not a git command
fcc git setting credential helper
To set the PGP program to GnuPG within a .gitconfig
git config --global gpg.program gpg
To setup a .gitconfig
to sign commits for a repo
git config commit.gpgsign true
The above config line will sign all commits and not require
-S
flag when making a commit.
To setup git to sign all commits from the localhost
git config --global commit.gpgsign true
To setup GnuPG to always sign commits, and to not require a passphrase π€, gpg-agent to th rescue β
gpg-agent and gpg as of July 3 2018 share the same version, ie. v2.2.8
brew install pinentry
gpgconf --kill gpg-agent
gpg -K --keyid-format SHORT
gpg2 --gen-key
gpg2 -K --keyid-format SHORT
sec rsa2048/12345678
git config --global user.signingkey 12345678
To sign a commit using GnuPG
git commit -S -m "mr fancy commit message"
Setting up GitHub to work with GnuPG π
Adding a GnuPG public key to GitHub π
- List the GnuPG keys for both public and private key pairs.
gpg --list-secret-keys --key-id-format LONG
- Copy the GPG key ID
sec rsa2048/012345678ABCDEF0 2018-07-02 [SC]
Ex
echo "012345678ABCDEF0" | pbcopy
- Put the GPG public key into the system clipboard.
gpg --armor --export 012345678ABCDEF0 | pbcopy
- Then paste the contents of the clipboard into GitHub settings for working with keys.
https://github.com/settings/keys
The above link will only work if logged into GitHub.
Edit config.fish
set -gx GPG_TTY (tty)
iTerm2 may need to be restarted for gpg to pick up on new passphrase settings, and the passphrase may need to be entered at least once for the gpg-agent to capture the passphrase permanently.
Working with git hooks π
π¨ When modifying or editing hooks at a
$USER
scale, I consider it a best practice to run,git init
in the project repo in order for updates made withint thehooks
dir to ripple down to the project repo.
Working with Identities π
For a good explanatioin about working with different git user
accounts in a .gitconfig
see this
TL;DC
Within a git repo run
git identity github
to set the identity for a particular git project.
Global
user.name
anduser.email
will need to be unset with this approach
Working with Large git Repositories π
Ex
To remove unecessary objects from a git repository, ie. the DerivedData and Pods directory from a Objective-C project / repo.
- Install bfg
brew install bfg
bfg requires some form of Java to be installed because it is written Scala
- Clone and mirror the repo in question
git clone --mirror --recursive [email protected]:[USER]/repo.git
- Remove the Pods and DerviedData objects from the repo
bfg --delete-folders 'DerivedData,Pods' repo
- Reflog the repo and do a git garbage collection
cd repo.git
git reflog expire --expire=now --all && git gc --prune=now --agressive
- Remove references to pull requests for the repo, specific to GitHub
git for-each-ref --format 'delete %(refname)' refs/pull | git update-ref --stdin
The above git command removes references to pull requests which will prevent the newly refloged repo from being pushed to GitHub.
- Push the newly refactored repo to GitHub
git push origin master
Optional
If the repo has already been cloned, and one wants to update it with the newly pushed objects from GitHub
- Fetch the remote changes from GitHub
git fetch origin master
- Merge the changes into the HEAD of the already cloned repo in question.
git reset --hard origin
Useful Links Working with Large git Repositories π
git Troubleshooting π
Scenario I often start working in a project that is using git and forget that I am on the master branch π΄π» and begin to modify files ie. update packages in a package.json using npm or what not, and even though I have not stagged or committed the files, without the project being in source control it would be rather difficult to undo the changes I made using npm. All that said, the easiest way I can think of to undo modified / changed files in a git repository that have not been stagged or committed is to run a
git checkout .
The above command will revert the above changes to a clean working state before the npm commands updated the package.json file.
git stash is an alternative way to save changes but also revert back to the clean working tree.
Troubleshooting GnuPG with git π
If a repo is showing / registering commits as unverified but other repos are showing verified compare the repo configuration files, ie. .git/config
of the problematic repo with the working repo. In my particular use case, my dotfiles repo had [user]
settings contained within the .git/config
that were making the commits for that particular repo univerified. π€·
To print the files that were changed for a specific commit
git show --pretty="" --name-only [123456f]
The complete git hash is not required, and only the short 7 char git hash is required, however if one can supply 41 char hex sequence that is preferred. π
To troubleshoot the below error messages
gpg: WARNING: server 'gpg-agent' is older than us (2.1.18 < 2.2.8)
gpg: Note: Outdated servers may lack important security fixes.
gpg: Note: Use the command "gpgconf --kill all" to restart them.
To restart an outdated gpg service
gpgconf --kill all
Troubleshooting forking, ie. pushing / pull local with remote and upstreams π
To fix the dreaded This branch is 12800 commits ahead of MrFancyRepo:master
- Pull upstream changes
git reset --hard upstream/master
To sync a local origin with it's upstream counterpart
git remote update
git reset --hard upstream/master --
git push -f origin master
- Push local upstream changes to remote origin
git push -f origin master
To fix error: insufficient permission for adding an object to repository database .git/objects
cd /path/to/repo.git
chgrp -R groupname .
chmod -R g+rwX .
find . -type d -exec chmod g+s '{}' +
To fix (shallow update not allowed)
git fetch --unshallow
git fatal The current branch master has multiple upstream branches, refusing to push
git config remote.origin.push HEAD
To restore from a detached head
git checkout master
Make sure to create a local branch if changes have been made.
To remove a file from source control tracking
git rm --cached /path/to/file/to/be/removed.js
To test, and make sure you can properly authenticate with a git server such as github.com or bitbucket.org
ssh -T [email protected]
ssh -T [email protected]
To undo the currently staged commits
git reset
the below block of text probably deserves a blog post of some sort, but don't really have an active blog going at the moment, so i guess this copy paste random braindump will have todo for the time being.
in short, i've been working with the freecad homebrew tap trying to get a working freecad formula file without much luck. there was an official 0.19.2 release earlier in 2021, however that build did not quite work on macos and from what i understand the macos CI was disabled when the CI was using travis due to macos cpu time limitations ie. the (builds were taking too long).
so when attempting to build freecad from the 0.19.2 tarball which brew install will do, because it is the most recent (insert air quotes) stable version of freecad. however the build can fail due to the capitalizations of certain files containing XERCESC instead of XercesC.
i still would prefer to build from the 0.19.2 tarball and use the pr #4960 from upstream freecad repo to fix the brew install issues. however applying the commit patch from the PR that github provides will fail due to the files having multiple changes, and for the fact there the PR fixes a file that isn't part of the 0.19.2 release.
now that, that is out of the way, a couple of useful commands and links below for attempting to backport a PR patch/diff to fix a bug
- a pretty good blogpost or tech article about using patch and diff
https://www.howtogeek.com/415442/how-to-apply-a-patch-to-a-file-and-create-patches-in-linux/
one way to go about backporting the PR is to download the tarball make the necessary changes to the affected files. then extract the tarball again, and then create a patch file using the diff command. homebrew should be able to "slipstream" the patch into the install process.
so to create a patch from the two extracted tarballs of the freecad 0.19.2 release.
echo "below is the cmd i used to create a custom patch file of pr4960 for the 0.19.2 release"
diff -ruN FreeCAD-0.19.2/ FreeCAD-0.19.2.pr4960/ > backport.pr4960
some other useful commands i came across were,
git am ...
git apply ...
π those two commands are useful for working with patch files in a git repository
to generate a .patch
file from a working commit id in a git repository
$ git format-patch -1 commit-id
a good stackoverflow answer about resolving whitespace issues with git patches
https://stackoverflow.com/a/34883081/708807
a decent stackoverflow answer about troubleshooting git merge conflicts after attempting to apply patch file
https://stackoverflow.com/a/63148678/708807
a decent writeup on howto resolve git merge conflicts which can happen when attempting to apply a patch file to a working git repository
https://phoenixnap.com/kb/how-to-resolve-merge-conflicts-in-git
To completely wipe local origin changes with remote counter parts for a specific branch [credit](https://stackoverflow.com/a/8135023/708807)
git remote
git reset --hard upstream/master --
the above command should sync all commits from upstream master to origin master, so that both branches are even at the time of issuing the commands.
To find the commit for a particular file for when it was first checked in to a git repo
git log --diff-filter=A -- /path/to/file
the complete path to the file must be present, ie. just specifying only a filename will NOT π work.
Useful Links π π
- digitalocean, How To Rebase and Update a Pull Request
- do not issue pull requests to master branch
- gist.github.com | how to test / experiment with github PR
- git-scm.com - working with submodules
- Changing a remote's URL in a git repo
- StackOverflow - Great π answer for working with SVG on GitHub
- DigitalOcean - Setting Up a
git
server - StackOverflow - git mergetool
TODOs π
-
add a Table on Contents to this document. -
figure out how to work with submodules, ie.add
,commit
,push
- add a
git lzy
ie. a git lazy command to inclusively add commit and push all changes in all repos, submodules included.