As I described here previously my goal was to establish central git repository and avoid redundant round-trips to TFS whenever possible.
To achieve this now you probably want to follow my advise in the above mentioned article about having user.name=<tfs account name without domain>
and same user.email
for everyone fetching changes from TFS.
In the latest git-tfs sources this was already fixed, so you don’t need to set this kind of things.
When I established central repository I faced some inconveniences: firstly pattern “checkout master, check central repository for changes already there but not in your local repository, pull new changes from TFS, push to central repository if anything new was pulled, checkout old working branch again, optionally rebase it onto master” was very boring and very repeatable. And the second inconvenience: this pattern should be repeated each time something new appears in TFS. I want to have some scheduled updating so I wouldn’t think about such things as when and how I should update latest version etc.
Well, it is perfect target for automation. So now I want to share my bash script that does these things and saves you several dozens of key-pressing each time you need get changes from TFS.
#!/bin/sh check_err() { # parameter 1 is last exit code # parameter 2 is error message that should be shown if error code is not 0 if [ "${1}" -ne "0" ]; then cat '~temp.log' echo ${2} rm -f '~temp.log' > /dev/null exit ${1} fi; rm -f '~temp.log' > /dev/null } echo "$(date) Update launched" if [ ! -z "$(git status --porcelain)" ]; then echo "$(date) Your status is not clean, can't update" exit 1; fi; branch_name="$(git symbolic-ref HEAD 2>/dev/null)" branch_name=${branch_name##refs/heads/} if [ ! "$branch_name" == "master" ]; then git checkout master fi; echo "$(date) Pulling from central repo first to avoid redundant round-trips to TFS..." git pull > '~temp.log' check_err $? "Pulling from central repo failed" echo "$(date) Pulling from TFS..." git tfs pull -d > '~temp.log' check_err $? "Pulling from TFS resulted in error"; remote_conflicting_commits="$(git rev-list origin/master ^master)" if [ ! -z "$remote_conflicting_commits" ]; then echo "origin/master has conflicting commits, can't push" exit 1; fi; local_commits_to_push="$(git rev-list master ^origin/master)" if [ -z "$local_commits_to_push" ]; then echo "$(date) Central repo is up-to-date, nothing to push" else echo "$(date) Pushing updates to central repo" git push --tags origin master > '~temp.log' check_err $? "Push to central resulted in error"; fi; if [ ! "$branch_name" == "master" ]; then git checkout $branch_name if [ "$1" == "-r" ]; then echo "Rebasing $branch_name on master"; git rebase master fi; fi;
This script assumes you want master
branch to mirror TFS and rebases your working branch onto new changes only if you have specified -r
switch. And for the second inconvenience you have just to set-up some dedicated working copy and run this script each, say, five minutes in it. It is very easy to do with built-in Windows Task Scheduler:
- Go to Start -> Administrative tools -> Task Scheduler
- Click Create Task on the right side
- Check radio button ‘Run whether user is logged on or not’
- Select Triggers tab, click ‘New’. Set Start=’One time’ and ‘Repeat task every’ whatever, check ‘Enabled’, click OK.
- Go to Actions tab, ‘New’. Set Program/script to ‘
cmd
‘, Add arguments=’/c "sh.exe update >> log.txt"
‘ and in the Start in field put path to your working copy, dedicated to central repository updating.
That’s all. Now you should have updates regularly without any efforts. It is important to note though, that script assumes your remote named origin/master
and noone pushes conflicting changes to central repo’s master
branch.
And not forget to add /log.txt
to .gitignore
. Otherwise your updates will just fail to start because of not clean working tree.