Cleaner [[git]] History *********************** #HTML# Mark Jason Dominus ++++++++++++++++++ Plover Systems Co. ++++++++++++++++++ mjd@plover.com v0.1 (Dec, 2013) ++++++++++++++++ ###Slides at ### ### http://perl.plover.com/yak/cs/ ---------------------------------------------------------------- [[Git]] ******* * One of git's strengths is that has good tools for tracking development history * Logging is fast and complete * We are not taking advantage of this * Git is tracking history * But our history is so complicated nobody can understand it ---------------------------------------------------------------- #IMG# tangled.png ---------------------------------------------------------------- * Here it is in another format, produced by git log --graph --oneline #IMG# tangled-text.png ---------------------------------------------------------------- * If you have been thinking "Yeah, this sucks", I agree * If you thought it was git's fault, I disagree * I think it's because we are doing it wrong ---------------------------------------------------------------- * This is what I think it should look like #IMG# untangled.png ---------------------------------------------------------------- * I think this will be easy to fix: #HTML#
#HTML# #HTML# Stop merging changes from master #HTML#
---------------------------------------------------------------- Stop merging changes from [[master]] ************************************ #IMG# tangled-hi.png ---------------------------------------------------------------- Stop merging changes from [[master]] ************************************ * You may not know you are doing this * The problem is in [[git-pull]] #HTML##HTML# #HTML# git-pull = git-fetch + git-merge #HTML#
* [R[Please stop using git pull]R] ---------------------------------------------------------------- Stop merging changes from [[master]] ************************************ #HTML##HTML# #HTML# git-pull = git-fetch + git-merge #HTML#
* Stop using [[git-pull]] * Just use [[git-fetch]] exactly the same way * It gets the same arguments * It fetches the same things * But it doesn't do a merge ---------------------------------------------------------------- Stop merging changes from [[master]] ************************************ * Develop your topic branch separate from [[master]] #IMG# history1.png * [[git-fetch]] will acquire changes from [[master as before]] * It just won't merge them to whatever your current branch happens to be #IMG# history2.png ---------------------------------------------------------------- * When the topic branch is ready, "land" it on [[master]]: git checkout master git merge topic * This automatically generates a commit message like "Merge branch 'topic' #IMG# history3.png * If you don't like that, you can: git merge [C[-m 'This is a better message']C] topic * Or, after the commit is made, modify the commit message with: git commit --amend ---------------------------------------------------------------- Stop merging changes from [[master]] ************************************ #HTML#“But what if my code won't work with the current [[master]]?”
* There are several good ways to deal with that * But it depending on what you want * Which means you have to know what you want ---------------------------------------------------------------- Undo the merge ************** * If you don't like the outcome of the merge, it's easy to undo * Suppose you've done this: git checkout master git merge topic #IMG# history3.png * You can always throw away the most recent commit with: git reset --hard HEAD^ * After that we're back to this: #IMG# history2.png * Then you can checkout [[topic]] and continue from there as before ---------------------------------------------------------------- [[rebase]] ********** * A better way to get the new code from [[master]] into your topic branch is with [[rebase]] * [[git-rebase]] will try to redo all your changes starting from somewhere else git checkout topic git rebase origin/master * The result: #HTML#Before | After #HTML# | |
---|---|---|
#HTML# | #HTML# | #HTML# |
“That's too scary. What if I don't like what it does?”
* No problem * Git means never having to say "Oh, crap, I screwed up" * [C[git reset --hard ORIG_HEAD]C] will put [[topic]] back where it was ---------------------------------------------------------------- [[rebase]] ********** * Alternative: Instead of rebasing [[topic]], try this: git branch topic-rebased topic git checkout topic-rebased git rebase master #IMG# history5.png * Now you can compare [[topic]] and [[topic-rebased]] to see if you like the result * Shortcut: #* git checkout -b topic-rebased git rebase master ---------------------------------------------------------------- [[git-vee]] *********** * I have a script for comparing branches with the rebased versions #IMG# history5.png * The command [[git vee topic topic-rebased]] produces this: #HTML##HTML# = e03d8a2 (topic-rebased) more changes to files named a #HTML# = 2713271 more a files #HTML# = 95536a3 add some files named a #HTML# * c34f8b9 (master) replace c with c2 and c3 #HTML# * 769e6ad work on b files #HTML# | = 2802301 (HEAD, topic) more changes to files named a #HTML# | = 4cf89e7 more a files #HTML# | = 1c1bb18 add some files named a #HTML# |/ #HTML# o 2f9d24e add a, b, and c #HTML#* It shows the V-shaped history of both branches * back to the latest common ancestor * [C[=]C] marks commits that are the same in both branches * [C[*]C] marks commits that are not in both branches * It's in [[~mjd/bin/git-vee]] on dev if you want to try it ---------------------------------------------------------------- [[rebase]] ********** #HTML#
“But what if the patches don't apply?”
* Then you have to resolve a conflicted merge * You would have had to do that with [[git-pull]] anyway * After the conflicts are resolved and commited, you use: git rebase --continue ---------------------------------------------------------------- [[rebase]] ********** #HTML#“But what if I mess everything up?”
* Once the rebase is finished you can still undo it * If you haven't done another rebase since then: git reset --hard ORIG_HEAD * If you're still in the middle of the rebase and you want to give up: git rebase --abort * That puts everything back the way it was as if you had never tried [[rebase]] * Then you can call for help * I will be glad to help * I bet Ryan will be too * Other volunteers? ---------------------------------------------------------------- [[git-pull --rebase]] ******************** #HTML#“But git-pull is convenient and simple!”
#HTML#“I don't want to change my workflow and do separate fetch and merge!”
* No worries! The problem is with the merges. * If you do [[git-pull --rebase]] it will do fetch + rebase instead of fetch + merge. * To set this up to happen automatically, run this one time: git config --global --add 'pull.rebase' 'true' * That adds to your `.gitconfig`: [pull] rebase = true ---------------------------------------------------------------- Merging [[master]] anyway ************************* * "But I really do want to merge [[master]]" * That's fine with me, do what you like * My only objection is to *unintentional* merges #HTML##HTML# #HTML# Just stop using git-pull all the time #HTML#
* That's all I'm asking for ---------------------------------------------------------------- #RTIMG# sen.jpg Thank you! ********** * Any questions? ---------------------------------------------------------------- ----------------------------------------------------------------END