Configure git:
git config --global user.name "Your Name Comes Here"
git config --global user.email you@yourdomain.example.com
git config --global color.diff auto
git config --global color.status auto
git config --global color.branch auto
git config --global core.autocrlf false
git config --global core.savecrlf false
git config --global diff.renames true
git config --global merge.renameLimit 999999
git config --global diff.renameLimit 999999
git config --global core.excludesfile ~/.gitignore_global
You can now edit the global ignore file:
# Ignore project files from PHPStorm
.idea/*.xml
.idea/.name
.idea/scopes
.idea/*.iml
Some nice settings:
git config --global alias.st status
git config --global alias.ci commit
git config --global alias.br branch
git config --global alias.co checkout
git config --global alias.df diff
git config --global alias.undolast 'reset --soft HEAD^'
git config --global alias.datetag '!git tag `date "+%Y_%m_%d_%H%M"`'
git config --global branch.autosetuprebase always
git config --global push.default current
Checkout the first version with git:
git clone idefix.fechner.net:masterthesis.git masterthesis
Have several copies on several places and sync it with the master server (like svn):
mkdir repo
cd repo
git init repo
git pull ssh://user@server/dir/
git remote add origin git@server:pluginname.git
git config branch.master.remote 'origin'
git config branch.master.merge 'refs/heads/master'
git push origin master:refs/heads/master
Remove remote Branch
git push origin :branchname
Split one Repo into Several
We have migrated now a repo but it contains several directories which should be splitted into seperate repos. The structure looks like:
git-root/
AutoInvite
phpraider
This can be done with filter-branch. At first checkout the repo as often as you want to split it:
git clone git@server:auto_invite AutoInvite
git clone git@server:auto_invite AutoInvite_phpRaider
Now we remove everything from the repo which should not be in:
cd AutoInvite
git filter-branch -f --tree-filter 'rm -Rf phpraider' --prune-empty -- --all
git gc
cd ..
cd AutoInvite_phpRaider
git filter-branch -f --tree-filter 'rm -Rf AutoInvite' --prune-empty -- --all
git gc
cd ..
Now we rewrite the root directory:
cd AutoInvite
git filter-branch -f --subdirectory-filter AutoInvite -- --all
git gc
cd ..
cd AutoInvite_phpRaider
git filter-branch -f --subdirectory-filter phpraider -- --all
git gc
cd ..
Push the new repos to a gitolite server:
cd AutoInvite
git push --all git@localhost:AutoInvite
cd ..
cd AutoInvite_phpRaider
git push --all git@localhost:AutoInvite_phpRaider
cd ..
Remove everything from your local repository:
git for-each-ref --format="delete %(refname)" refs/original | git update-ref --stdin
git reflog expire --expire=now --all
git gc --prune=now
Better Tool
Maybe a better tool is: https://github.com/newren/git-filter-repo
Only keep one folder:
git-filter-repo --force --path software/telegram\ analyser
To remove the folder in the other repository:
git-filter-repo --force --path software/telegram\ analyser --invert-paths
To move the newly filtered project into ROOT path you can execute:
git-filter-repo --path-rename software/telegram\ analyser/:
Modify First Commit
The problem here is that the first commit cannot be changed with the rebase command. So we have to create a new first commit befor we can modify the real first commit:
git symbolic-ref HEAD refs/heads/newroot
git rm --cached -r .
git clean -f -d
# touch .gitignore && git add .gitignore # if necessary
git commit --allow-empty -m 'Initial commit'
git rebase --onto newroot --root master
git branch -d newroot
Now we can change commits with rebase -i as usual.
Merge Two Git Repositories
git remote add repotomerge /path/to/repo
git fetch repotomerge
git merge repotomerge/<branch to merge>
git gc
Merge Two Git Repositories into one with own Sub Folders
We have two git repositories called subfolder1.git and subfolder2.git, both repositories will contain several branches and we want to build up a complete new structure in the way:
base directory
|- subfolder1 (from repository subfolder1)
|- subfolder2 (from repository subfolder2)
|- more folder (newly added)
- file1 (newly added)
The repositories are available via git clone from:
http://server/subfolder1.git
http://server/subfolder2.git
We use the following script to checkout the repository and rewrite the path and merge everything into one repoistory with complete history and all branches:
#!/bin/bash
# (c) 2013 Matthias Fechner
me=$(basename "$0")
TMP=$(mktemp -d /tmp/$me.XXXXXXX)
echo
echo "building new repo in $TMP"
echo
set -e
cd "$TMP"
mkdir new-repo
cd new-repo
git init
cd ..
x=0
while [ $# -gt 0 ]
do
repo="$1"
shift
dirname=$(basename "$repo" | sed -e 's/\s/-/g')
dirname=$(basename "$dirname" | sed -e 's/.git$//')
echo "Clone $repo"
git clone --bare "$repo" "$dirname"
cd "$dirname"
echo "Checkout all branches"
for remote in `git branch -r | grep -v master `; do git checkout --track $remote ; done
git checkout master
echo "Remove reference to origin, so we cannot push by accident"
git remote rm origin
echo "Move all files and directories to new location"
git filter-branch --index-filter 'git read-tree --empty; git read-tree --prefix="$dirname/" "$GIT_COMMIT"' -- --all
cd ..
cd new-repo
git pull --no-commit ../$dirname
[ $x -gt 0 ] && git commit -m "merge made by $me"
cd ..
x=$(( x + 1 ))
done
The script is named mergeGitRepos.sh and is executed this way:
mergeGitRepos.sh http://server/subfolder1.git http://server/subfolder2
After it is done. you can copy your missing folder (more folders) and your missing files and commit them as usal.
Second Approach
The script failed and do not what I wanted. New approach is to filter every repository to get the correct path there.
At first we copy the repository on the server so we work on a test repository, that is important, because we will overwrite it several times to get everything merged.
cp -r repo.git repo_save.git
Now the real work:
git clone http://server/repo_save.git
cd repo_save
for remote in `git branch -r | grep -v master `; do git checkout --track $remote ; done
git checkout master
git remote rm origin
git filter-branch --index-filter 'git read-tree --empty; git read-tree --prefix="subfolder/" "$GIT_COMMIT"' -- --all
git push -f --all http://server/repo_save.git
git push --tags http://server/repo_save.git
cd ..
rm -rf repo_save
Redo this for every repository. Now all repositories should have there correct folder displayed for all branches.
Now we combine them to one repository:
mkdir new-repo
cd new-repo
git init
git remote add origin http://server/repo1_save.git
git fetch --all
git fetch --all -t
git pull
git checkout master
for remote in `git branch -r | grep -v master `; do git checkout --track $remote ; done
git checkout master
git remote rm origin
git remote add origin http://server/repo2_save.git
git fetch --all
git fetch --all -t
git merge origin/master
... merge all branches ....
git remote rm origin
git remote add origin http://server/new-repo.git
git push --all
git push --tags
cd ..
rm -rf new-repo
Now you have your new repository on the server in new-repo.git.
Clone it, test it thate everything like you expected it. If everything is fine, remove all backup and you are done.
Delete files from git history
You have a project and you want to make it public but you commited password to your repository? Lets say the passwords are in the file bin/config, so we can do the following:
git filter-branch --index-filter 'git rm -r --cached --ignore-unmatch bin/config' HEAD
May 01 | Bind | 8 min read |
Mar 26 | Altium | 1 min read |
Jan 12 | Changelog | 1 min read |
Nov 27 | Git on Windows | 2 min read |
Oct 22 | Automatic Deploy | 2 min read |