Inhaltsverzeichnis
GIT
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:
- ~/.gitignore_global
# 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:
- mergeGitRepos.sh
#!/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