Manually setting the authored date in a git commit
After my last post about splitting and otherwise reworking git commits via rebase I needed a way to manually set the authored date on a git commit, since I had overwritten that on some old commits. And having earlier commits come a month after later ones looks a bit silly. So I searched around in vain for how to set that field manually.
Thankfully, deskin on #git was able to quickly point me in the right direction. The docs for git-commit-tree talk about the environmental variables that determine the date, author, etc. Git commit honors these (at it probably actually uses git-commit-tree, behind the scenes). So to change the date on a commit (in the middle of a git-rebase, git-reset just set the environmental variable inline, thus (if you use bash):
GIT_AUTHOR_DATE='2008-09-29 01:09:07' git commit
This will not work on an—amend, though, since that is intended to just keep the same time and other settings for the commit, but just add some more changes. These means to change the time you must follow the more complicated workflow in my previous post.
Editing git commits with rebase, in particular splitting commits
So I have a project on github that I wanted to rework some of the commits before anyone sees them. I used to manage the project via svk, so the commits are squashed down into less granular blocks than I want for reviewing via an interface like githubs. ‘git commit—amends’ for, well, amending the last commit you made, but if the changes are further back than that, you get into the deep magic of rebasing. Much of this is discussed in the man pages, and docs for git-rebase but that can be hard to follow until you really understand what is happening.
‘git-rebase -i SHA_OF_PARENT’ lets you rollback to the commit before where you want to start mucking with stuff, mark which commits you want to edit, and then recommit them. For the simplest use case, just editing the commit messages, you just ‘commit—amend’ each time git-rebase pauses, ‘git-rebase—continue’ and repeat until done. This workflow is explained reasonably well in the docs, the only thing to emphasize that will help you understand the more complex cases is that it works by rebase pausing just after each commit you marked for editing, so that you can amend (which amends that last commit) and continue.
This segues into how splitting up of commits works. You mark for editing and rebase as usual. When it pauses after the commit you want to split up, you ‘git reset HEAD^’ to rewind one commit, while keeping the changes in the filesystem. So at this point, if you committed and continued, it’s be exactly like the simpler workflow. Instead, though, you can split up the changes: git add each subset of changes, committing them with the appropriate message. Then when you are done, rebase—continue again.
With these techniques you can rework the history completely into a better organized, more easily follow-able set of chunks. It does leave a couple problems, if it is a repo you have already pushed you will get a ‘not strictly subset’ error. If you know nobody has pulled from it, you can just push—force, but I make no guarantees what this might do to the state of other peoples repos that are pulling from the same master, especially if they are mucking about similarly.
The other problem is that this resets the authored by date on the commits, since it’s essentially nuking one commit and making a new one. I’ll discuss this in the next post manually setting the authored date in a git commit
deskin
Importing a large sql file directly into mysql via a rails migration
class CreateZipCodes < ActiveRecord::Migration
def self.up
#Loading that large of a YAML file can cause problems
zip_code_file = File.expand_path(File.join(File.dirname(__FILE__), "..", "zip_codes.sql"))
config = ActiveRecord::Base.connection.instance_variable_get('@config')
`mysql -u#{config[:username]} -p#{config[:password]} #{config[:database]} < #{zip_code_file}`
end
def self.down
drop_table :zip_codes
end
end

Articles via rss or email