The build system I work with usually requires that the project data is committed to the local repository before a full build can be performed. This -- along with my usual habit of committing frequently and rebasing before pushing to the public repo -- means I usually have a stack of commits on top of the remote head. Most of them have commit messages like "s" because I know they will be squashed.
The situation I have here is automating one of the steps of rebasing the list of commits. I know that all the changes I make to a certain file should not be pushed to the public repo, and I was looking for a way to edit each commit to split off the changes to that file into separate commits which I will squash in a later rebase.
For example, here's the commits I have on top if the origin's HEAD:
* 6f42745 (HEAD, master-dave) s
* b33bc68 s
* 0b787e8 s
* 3d47e9e s
* ae45dec brought pkg up-to-date with master branch
* dd87ec1 s
* 96fd4ef DD: dave dev
* 422cf73 (origin/master, master) Add missing build scripts.
I want to iterate through all commits from master..master-dave, extract changes to ./file.txt, giving me:
* 6f42745 (HEAD, master-dave) s
* ------- DD (changes to file.txt)
* b33bc68 s
* ------- DD (changes to file.txt)
* 0b787e8 s
* ------- DD (changes to file.txt)
* 3d47e9e s
* ae45dec brought pkg up-to-date with master branch
* dd87ec1 s
* 96fd4ef DD: dave dev
* 422cf73 (origin/master, master) Add missing build scripts开发者_C百科.
And finally, I would run git rebase -i origin/master, squash all the "DD" commits together, all the "s" commits into "brought pkg up-to-date with master branch", re-order them, update master, and push to origin, finally ending up with:
* ------- (HEAD, master-dave) DD: dave dev
* ------- (origin/master, master) brought pkg up-to-date with master branch
* 422cf73 Add missing build scripts.
I'm pretty sure the answer lies with git filter-branch, but I can't figure out how.
EDIT:
- --autosquash fixes the annoyance of the "s" commits, but that's not the main question. I still don't know how to split out the changes to a specific file, which must happen before I squash them.
- smudge/clean filters are nifty, but I'm not doing keyword replacement, and I don't think the changes I want to maintain on my personal branch are going to be predictable enough to script. I think I'm always going to have to be at least one commit ahead of the public master.
http://technosorcery.net/2010/02/07/fun_with_the_upcoming_1.7_release_of_git_rebase_--interactive_--autosquash.html
This should tell you how to autosquash. Instead of marking the commit with s, mark it with !squash.
It looks like you should be maintaining your own branch for all the DD commits. Then just manage merging with the main branch.
If the changes to the file that you want excluded are due to environment setup, look at smudge/clean scripts instead. This will enable you to commit relevant changes to that file and omit any changes that are only for your environment. This is usually db connection strings that differ from one dev to the other.
Take a look here: http://progit.org/book/ch7-2.html
精彩评论