I'm trying to refine a personal git workflow to something a little easier to deal with.
Here's some background of how I'm using git for purposes of this post:
A single developer who is the only one working on the repository.
A single copy of the repository that is stored on the local machine.
Only two branches "dev" and "master".
All work done on "dev".
What I'm trying to accomplish is to get to the point where the only commits made to the "master" branch are working production versions based on the confrimed stable "dev" code.
Effectively, what I'm looking to do is:
When everything in "dev" is tested and ready to go, update "master" to be an exact clone of the "dev" branch file tree.
Make minor modifications to "master" to update version numbers, etc...
Commit to the updated "master" branch.
Make a new tag from the "master" branch.
The way that I'm approaching the first step is to checkout the "master" branch and then to run:
'git diff master dev | git apply -'
From what I understand, this effectively blows away anything in "master" and replaces the entire tree with the contents of "dev". Running "git status" appears to show that this is doing what's expected based on #1 above.
So, the first question: Is that correct?
After the "master" branch has received these updates, I run my script over to update version numbers in files. Then, I just run a standard "git add ." and "git commit -a" to add all the changes. Finally, I make a new tag and return to the "dev" branch to start coding again.
So, the other question: Is there anything in that process that is going to cause issues?
UPDATE: I should have put this in the first time, but the reason I'm not simply using merge is that changing the version number on master and then trying to merge with changes in dev causes merge conflicts. I know they are irrelevant, but it still stops the process. I've used "merge -Xtheirs {branch}" before to deal with it, but I'm not sure about that either.
UPDATE2: Here's some stuff that I know does not work. I've put together a bash script that works on Mac OSX. The first one attempts to use merge:
#!/bin/bash -x
####################
### file: merge1 ###
####################
### clear out the old stuff so you can rerun
rm -rf .git
rm *.txt
### setup the repository
git init
### ignore merge and output files for clarity sake
echo -e "output*\nmerge*" > .gitignore
git add .gitignore
### make the intial commit and move over to dev
git commit -m "Initial commit"
git checkout -b dev
### add stuff to test1.txt in dev
echo -e "FILE1 LINE\nVERSION-XXX\nFILE1 LINE" > test1.txt
echo -e "File2 LINE\nVERSION-XXX\nFILE2 LINE" > test2.txt
### add the files and commit
git add .
git commit -m "Created test1.txt and test2.txt in dev."
### output the state of test1.
cat test1.txt > output-dev-test1-a.txt
cat test2.txt > output-dev-test2-a.txt
### move to master and do a first merge which will work
git checkout master
git merge dev
### Update the version numbers in master and commit it
sed -i "" -e 's/VERSION-XXX/VERSION-1.0/g' test*.txt
git commit -am "Updated version to 1.0 on master"
cat test1.txt > output-master-test1-a.txt
cat test2.txt > output-master-test2-a.txt
### switch back to dev and commit an update to test1.txt
git checkout dev
sed -i "" -e 's/LINE/CHANGED/' test*.txt
git commit -am "Updated content in test*.txt on dev"
### dump test1.txt for reference.
cat test1.txt > output-dev-test1-b.txt
cat test2.txt > output-dev-test2-b.txt
### swtich back to master
git checkout master
######################################################################
### BREAK
######################################################################
### this is where the merge fails because of a conflict
git merge dev
The other way I tried this was with -Xtheirs, which looks like it works at first, but it doesn't update everything. To see that, remove the last few lines after the BREAK above and replace them with:
### merge with -Xtheirs works here. Proper version "XXX" is showing.
git merge -Xtheirs dev
### but if we update the version number one more time on master
sed -i "" -e 's/VERSION-XXX/VERSION-2.0/g' test*.txt
git commit -am "Updated version to 2.0 on master"
### dump reference file
cat test1.txt > output-master-test1-b.txt
cat test2.txt > output-master-test2-b.txt
### Now, go back to dev and change something in only one of the files
git checkout dev
sed -i "" -e 's/CHANGED/ALTERED/g' test2.txt
git commit -am "Altered only test2.txt on dev."
cat test1.txt > output-dev-test1-c.txt
cat test2.txt > output-dev-test2-c.txt
### are finally return to master and merge again
git checkout master
git merge -Xtheirs dev
### dump reference file
cat test1.txt > output-master-test1-c.txt
cat test2.txt > output-master-test2-c.txt
There are no conflicts, but 'output-master-test1-c.txt' shows 'VERSION-2.0' instead of 'VERSION-XXX' which is desired. This appears to have happened because there were no changes to the file. The 'output-master-test2-c.txt' file has the expected 'VERSION-XXX' sting. The problem, of course, is that the find and replace that tried to update to version 3.0 would miss in test1-c because it wouldn't recognize the 2.0 part of the VERSION sting.
At its core, Git is a version control tool for software developers who work in a distributed development environment that allows multiple developers to work on a single project without stepping on each other's code. The web developers at eXcelisys use it precisely for that purpose.
The GitHub flow branching strategy is a relatively simple workflow that allows smaller teams, or web applications/products that don't require supporting multiple versions, to expedite their work. In GitHub flow, the main branch contains your production-ready code.
You should use real merges instead of the diff/apply hack. This is as simple as
[master]$ git merge dev
When you run this on the master branch (shown in prompt) you will merge in all changes from dev. Afterwards you can update the version number, commit and create a tag
[master]$ git commit -a -m "New version number."
[master]$ git tag version-1.x
It's as simple as that.
In fact you don't really need a master branch at all, you can create a short lived release branch based on dev, create a tag there and delete the branch afterwards.
[dev]$ git checkout -b release dev
[release]$ git commit -a -m "New version number."
[release]$ git tag version-1.x
[release]$ git checkout dev
[dev]$ git branch -d release
I do something very similar (only when I'm the sole developer on my own software)...
I work SOLELY on the master branch. And at different 'versions', I create a dangling branch.
This enables me to get back to any previous version just by checking it out.
A - B - C - D - E - F
\ \
1.0 1.1
Easy and works good enough for my needs.
If I need to do some bug fixes to previous versions, i just work off of that branch and get them done.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With