Git for Experts
Some advanced repository manipulations.
Table of contents
- Ensure SSH Agent is running
- Split a subdirectory to its own branch
- Merge a branch into a subdirectory
- Revert a mass commit
- Add git tags retrospectively
- Git submodules
- Recover lost commits
Ensure SSH Agent is running
Not strictly Git, but useful when running on a server. Add to .bashrc
:
export SSH_AUTH_SOCK=~/.ssh/ssh-agent.$HOSTNAME.sock
ssh-add -l 2>/dev/null >/dev/null
if [ $? -ge 2 ]; then
ssh-agent -a "$SSH_AUTH_SOCK" >/dev/null
fi
Split a subdirectory to its own branch
This creates a new branch with the files in the subdirectory moved to the root directory, while keeping git history for those files.
git subtree split -P [subfolder/subsubfolder] -b [new-branch]
Merge a branch into a subdirectory
This keeps the history too
git checkout branchA
git checkout -b master
git merge -s ours --no-commit origin/branchB
git read-tree --prefix=directoryB/ -u origin/branchB
git commit -m "Merge branchB into the directoryB subdirectory"
git branch -D branchA
git branch -D branchB
git push origin --delete branchA
git push origin --delete branchB
Revert a mass commit
Note: below is number one
not lowercase L
SUBMODULES=$(ls -1 components/)
for SUBMODULE in ${SUBMODULES[@]}
do
pushd components/${SUBMODULE}
git revert --no-edit $(git log --oneline | grep "Add .keep file for empty directories" | awk '{ print $1 }')
popd
done
Add git tags retrospectively
GIT_COMMITTER_DATE="$(git show 0219549 --format=%aD | head -1)" git tag -a v2.0.0 0219549 -m "v2.0.0"
git push origin v2.0.0
Git submodules
Several commands related to managing submodules
Add a submodule
git submodule add -b master git@github.com:stellirin/my-sub-module.git my/sub/module
Download submodules after cloning project
git submodule update --init --recursive
Update submodules with remote updates
git submodule update --remote my/sub/module
Note: below is number one
not lowercase L
SUBMODULES=$(ls -1 my/sub/)
for SUBMODULE in ${SUBMODULES[@]}
do
git submodule update --remote my/sub/${SUBMODULE}
done
Update submodules with local changes
Use git commit
and git push
as normal from within the submodule. Later, from the project directory simply git add
the submodule. For example:
pushd my/sub/module
git add --all
git commit -m "My awesome commit"
git push
popd
git add my/sub/module
git commit -m "Update submodule reference for my/sub/module"
git push
Recover lost commits
use git reflog
to see a complete history of all commands that produced a commit.
This includes those times you made a commit while headless. You can even see the different commits produced when running git commit --amend
multiple times!