Git can “trace the evolution” of a specific method when passed -L
using the :<funcname>
variant. Let’s take a look at the history of this blog’s posts’ published
scope, which is used in most places that articles are listed out. You can see that git is able to identify the boundaries of the method even as the length changes and it prints out the full method with diff from each commit in the log, which is filtered to changes to that method.
$ git log -L :self.published:app/models/post.rb -n3
commit d1fbdf3b9a5bd37dd49d61c61ee0f51c75fdb806
Author: Caleb Hearth <caleb@calebhearth.com>
Date: Thu Feb 2 16:36:34 2023 -0700
Decree, LFW, new homepage, RSS-only posts
diff --git a/app/models/post.rb b/app/models/post.rb
--- a/app/models/post.rb
+++ b/app/models/post.rb
@@ -15,6 +15,6 @@
def self.published
all
- .reject { _1.frontmatter[:draft] }
+ .reject { _1.frontmatter[:draft] || _1.tags.include?("rss-only") }
.select { _1.date <= Date.today }
end
commit 37a830b625db4e60e0ffbfec881d693369706169
Author: Caleb Hearth <caleb@calebhearth.com>
Date: Fri Nov 12 11:39:48 2021 -0600
Publish posts published today
diff --git a/app/models/post.rb b/app/models/post.rb
--- a/app/models/post.rb
+++ b/app/models/post.rb
@@ -15,6 +15,6 @@
def self.published
all
.reject { _1.frontmatter[:draft] }
- .select { _1.date < Date.today }
+ .select { _1.date <= Date.today }
end
commit b1ed34a897af9ff2f882e140132a6e6045257b10
Author: Caleb Hearth <caleb@calebhearth.com>
Date: Mon Nov 1 10:33:13 2021 -0500
Don't filter out all posts
diff --git a/app/models/post.rb b/app/models/post.rb
--- a/app/models/post.rb
+++ b/app/models/post.rb
@@ -12,6 +15,6 @@
def self.published
all
- .reject { |post| post.frontmatter[:draft] }
- .reject { |post| post.frontmatter[:date] < Date.today }
+ .reject { _1.frontmatter[:draft] }
+ .select { _1.date < Date.today }
end
If you got excited and tried this on your own, you may have been disappointed to see a message like
fatal: -L parameter 'self.published' starting at line 1: no match
While Git knows how to do this for some languages (mostly the C family), it needs a bit of help for a lot of others including Ruby and Swift. Fortunately it’s as simple as adding one these lines (you only need the one relevant to your project’s language) to your project’s .gitattributes
*.rb diff=ruby
*.swift diff=swift
While Git provides a Ruby diff pattern, if you want to use Swift or other unsupported languages you’ll need to provide your own pattern. To do this, you’ll want to add something like this to your ~/.gitconfig (or .git/config in a project):
[diff "swift"]
xfuncname = ^[ \t]*((class|struct|func)[ \t].*)$
Update Paul Samuels was good enough to reach out to me with a more robust Swift regular expression that takes into account for the static
keyword:
[diff "swift"]
xfuncname = ^[ \t]*((class|struct|func|static)[ \t].*)$
It’s a Regex, so if that doesn’t quite fit your needs or if you need to put together an option for another language you can use your regular expression skills to figure that out. You need a pattern that will match the first line of the block you want to display, and Git will show lines up to the next match. This one will match classes, structs, and functions in Swift.
If you’d like this to be global so you don’t get that error in each new project, you can set up a global .gitattributes file for yourself like this:
$ git config --global core.attributesfile ~/.gitattributes
Then add the above lines to ~/.gitattributes.
Webmentions
What a cool idea! I never even knew you could do this, and I'm in git log
a lot. This goes right in the toolbox. Thanks Caleb!
Very minor side note: I find the font on this blog difficult to read!
Awesome, I knew this was possible and could have used it on Friday, but couldn’t be bother to look up how to do it in the git CLI
really useful! Thanks