Andrew Lock
andrewlock.net · Personal blog · on HN since 2018
Andrew Lock, a .NET developer, writes about ASP.NET Core, .NET internals and Git workflow tips.
What HN saysHN commenters link his post on git rebase --update-refs as a useful way to work with stacked branches, and cite his .NET guidance.
47HN people shared it
23linked it in comments
39stories submitted
381story points
4 months agolast shared
2018people per year2026
Most-shared posts
- 1Working with stacked branches in Git is easier with –update-refs (2022)16 people · 73 points · first shared 2022 · 15 comments on HN
- 2Using strongly-typed entity IDs to avoid primitive obsession (Part 1)3 people · 2 points · first shared 2019 · discussion on HN
- 3Closed class hierarchies (Exploring the .NET 11 preview – Part 4)2 people · 3 points · first shared 2026 · discussion on HN
- 4Adding simple email address obfuscation for your blog (2020)2 people · 2 points · first shared 2020 · discussion on HN
- 5Why is string.GetHashCode() different each time I run my program in .NET Core?2 people · 1 points · first shared 2018 · discussion on HN
- 6Homepage2 people · first shared 2022
- 7Understanding the Worst .NET Vulnerability1 people · 197 points · first shared 2025 · 63 comments on HN
- 8Fixing an old .NET Core native library loading issue on Alpine1 people · 68 points · first shared 2025 · 31 comments on HN
- 9Running .NET in the browser without Blazor1 people · 3 points · first shared 2025 · discussion on HN
- 10A Quantum RNG for .NET: The quantum measurement problem and many-worlds approach1 people · 3 points · first shared 2019 · discussion on HN
- 11Companies complaining .NET moves too fast should just pay for post-EOL support1 people · 3 points · first shared 2025 · 2 comments on HN
- 12Handy Docker commands for local development1 people · 2 points · first shared 2018 · 1 comments on HN
- 13Super-charging 'Git rebase' with 'Git absorb'1 people · 2 points · first shared 2023 · discussion on HN
- 14dotNET (OK, C#) gets union types1 people · 2 points · first shared 2026 · discussion on HN
- 15Working with stacked branches in Git (Part 1)1 people · 2 points · first shared 2025 · discussion on HN
What HN people wrote when they linked it
artimaeis · 2025-12-12
You specified working with web and .NET Core (now just called .NET). Given the scope of modern .NET I don't think I can recommend a single book, but I've tried to order this in how I see them as most to least impactful for a dev.
For web dev specific guidance it's hard to beat ASP.NET Core in Action by Andrew Lock. Check out Lock's blog too at https://andrewlock.net, it's a great source of new features happening in ASP.NET. He does go into publishing an app on both Windows and Linux, with a decent guide to both. But you'll probably want to read through MSDN docs on that as well, I don't think there's a book that goes in very deep on that.
For generally writing modern C# using .NET, I like Code like a Pro in C# by Jort Rodenburg.
For a quick tour of modern C# features C# 12 in a Nutshell by Albahari is basically the reference guide. 12 is the latest, grab any of them from probably 7 up for a decently modern take.
fatuna · 2026-05-16
Thanks for sharing this pearl of knowledge! This is brilliant. I found this page which explains using this function well: https://andrewlock.net/working-with-stacked-branches-in-git-is-easier-…
dmsnell · 2025-07-22
You can interactively rebase after the fact while preserving merges even. I usually work these days on stacked branches, and instead of using —-fixup I just commit with a dumb message.
git rebase -i --rebase-merges --keep-base trunk This lets me reorganize commits, edit commit messages, split work into new branches, etc… When I add --update-refs into the mix it lets me do what I read are the biggest workflow improvements from jj, except it’s just git.
This article from Andrew Lock on stacked branches in git was a great inspiration for me, and where I learned about --update-refs:
https://andrewlock.net/working-with-stacked-branches-in-git-is-easier-…
edfletcher_t137 · 2024-06-21
> - Somehow reviewers never seem to like the stack of PRs, my experience is they always react with disdain and/or confusion.
Are people sending multiple branches of the stack for review at once? It should only ever be the "bottom" branch out-for-review at any time.
> - Namely there would be review comments on the first PRs that then cause a cascade of merge conflicts in the follow-on PRs
This can still happen in the model above of course as you need to make changes to the bottom branch in response to review comments/requests.
However, as I noted elsewhere, `--update-refs` is an absolute god-send in those situations: https://andrewlock.net/working-with-stacked-branches-in-git-is-easier-…
It reduces a ton of manual work (scaled by how many branches you have stacked!) to one operation.
Hackbraten · 2024-05-16
I recently discovered `git rebase --update-refs` [1], which makes it much easier to work locally with stacked branches.
Before I learned that, I used to work with `git rebase` followed by a series of manual invocations of `git checkout -B`.
[1]: https://andrewlock.net/working-with-stacked-branches-in-git-is-easier-…
pjc50 · 2023-12-13
Great examples.
Is source generation becoming "trendy"? Microsoft have recently added more of it to C#, in order to support their AOT efforts. It's a bit infrastructure-heavy as it seems to be intended for point support for specific things, rather than a general purpose "write code to generate code" tool. But I wonder if there would be a market for such a thing. The architecture currently does not allow you to edit user source code, just add more code. I.e. it's not a preprocessor, it just has readonly access to the AST.
e.g. the regex generator https://learn.microsoft.com/en-us/dotnet/standard/base-types/regular-e…
(Reference blog post https://andrewlock.net/creating-a-source-generator-part-1-creating-an-… )
leleat · 2026-04-13
If I understood you correctly, you want to propagate changes in a branch to other branches that depend on it? Then --update-refs is for you[1]. That way, you only need to update the "latest" branch.
[1] https://andrewlock.net/working-with-stacked-branches-in-git-is-easier-…
fmorel · 2026-01-07
And dotnet run can now run single files of C# code, with the ability to import other projects and packages if needed.
#!/usr/bin/dotnet run
https://devblogs.microsoft.com/dotnet/announcing-dotnet-run-app/
https://andrewlock.net/exploring-dotnet-10-preview-features-1-explorin…
jbjbjbjb · 2025-12-05
I was reading this the other day when I came across this feature because I’m stacking PRs recently which I don’t usually do
https://andrewlock.net/working-with-stacked-branches-in-git-is-easier-…
Another commenter posted this link which was a bit more succinct
https://blog.hot-coffee.dev/en/blog/git_update_refs/
There isn’t much to it though, you just go to the branch and run git rebase with the update refs flag.
Munksgaard · 2025-07-22
Rebasing a stack of branches in git can also be pretty simple, with --update-refs. There's a good article here: https://andrewlock.net/working-with-stacked-branches-in-git-is-easier-…
algorithmsRcool · 2024-11-21
Another related effect of this is Protocol Ossification [0] which happens when implementers of a public API/Protocol surface area take implicit dependencies on common but not standardized behaviors of the API/Protocol implementation.
That being said, you can take proactive steps to defeat this. For example, the default Hash for strings in .NET is randomly seeded each time a process starts[1] in order to strongly dissuade folks from taking an implicit dependency on the underlying algorithm which is not guaranteed to be stable
[0] : https://en.wikipedia.org/wiki/Protocol_ossification
[1] : https://andrewlock.net/why-is-string-gethashcode-different-each-time-i…
Leftium · 2024-05-06
Is this an argument against strongly typed identifiers, or just an argument against adding too much meaning to the identifier?
I think if the identifier just adds what type of data it is identifying, the extra meaning will only become obsolete at the same time that data does. And the extra type information can help avoid/debug problems where the wrong type of id was used.
Compare with strongly typed ids/type branding:
- https://hw.leftium.com/#/item/39174998
- https://www.peakscale.com/strongly-typed-ids/
- https://andrewlock.net/using-strongly-typed-entity-ids-to-avoid-primit…
bryanlarsen · 2023-07-18
If your fancy SaaS git repo thingy doesn't support merge queue's, maintain your own using the `--update-refs` option to git.
https://andrewlock.net/working-with-stacked-branches-in-git-is-easier-…
Semaphor · 2022-12-05
> Is it just user-ids we should discuss or is it all kind of ids represented as an int?
Strongly typed ID’s are a thing advocated for in general [0], yes.
And they aren’t even inconvenient in some languages. Modern C# for example makes it very easy to use them [1].
[0]: https://andrewlock.net/using-strongly-typed-entity-ids-to-avoid-primit…
[1]: https://github.com/andrewlock/StronglyTypedId
bpugh · 2022-11-23
Git recently added a --update-refs option to rebase that makes dealing with this scenario a lot easier.
This post does a good job explaining how to use it: https://andrewlock.net/working-with-stacked-branches-in-git-is-easier-…
alexchro93 · 2022-07-22
Neat page from David Fowler. I didn't know about that one. Thank you.
To further explain why you want to use an AsyncLazy (or Lazy for synchronous programming) when working with ConcurrentDictionary I find this article to be helpful: https://andrewlock.net/making-getoradd-on-concurrentdictionary-thread-…
Genbox · 2022-02-07
- Daniel Lemire: https://lemire.me/blog/
- Andrew Lock: https://andrewlock.net/
- Steve Gordon: https://www.stevejgordon.co.uk/
- Scott Helme: https://scotthelme.co.uk/
- Phil Haack: http://haacked.com/
magicalhippo · 2021-09-13
> At least when the controllers are all classes I can unit test them.
So I've literally just jumped into this world, having never touched asp.net or similar before.
I looked into how to test the controller side of things, and came across this[1] post arguing that unit testing controllers weren't as useful as integration testing them.
Integration testing would definitely be useful, and something I will do, but I assume also a lot more time-consuming so perhaps not something we could do on a per-commit basis.
Would highly appreciate views on this topic.
[1]: https://andrewlock.net/should-you-unit-test-controllers-in-aspnetcore/
GordonS · 2021-05-15
If it helps, here's a related blog post but with a C# slant:
https://andrewlock.net/using-strongly-typed-entity-ids-to-avoid-primit…
The author refers to using primitives everywhere as "primitive obsession", and proposed using types instead.
shireboy · 2020-01-09
I think in most cases in HTTP, the server does not "know" the browser has canceled and so continues to execute. I believe it builds the response but can no longer send it because the underlying TCP connection is closed. So server continues to execute, but response bits never make it back to the client computer. WebSockets and HTTP2 may change that story somewhat.
Edit: actually, I think I'm wrong here. Server does get a canceled socket, and can pass that to server code. In ASP.NET Core, this: https://andrewlock.net/using-cancellationtokens-in-asp-net-core-mvc-co…
SideburnsOfDoom · 2018-03-12
> How does the runtime know if you can “Deconstruct” an object? It implicit based on whether the object implements the appropriate method?
Based on what I have read below, it's implicit; there's very little that the runtime has to know - it happens at compile time, with the compiler looking for a method with the name "Deconstruct" and the right type signature, and plugging that in during the compile.
The compiler already does a lot of heavy lifting codegen for language features like async / await
https://andrewlock.net/deconstructors-for-non-tuple-types-in-c-7-0/
http://www.techcartnow.com/new-c-sharp-7-features-in-action-deconstruc…
andimm · 2018-01-16
Links to the Second part don't yet work in part 1.
Therefore Part 2:
https://andrewlock.net/handy-docker-commands-for-local-development-par…
carapace · 2022-11-10
In the first place this is an error of RTFM kind. The "problem" behaviour is literally documented in the docs. However, in the second place, this is the wrong solution for the original problem. (The author links to https://andrewlock.net/why-is-string-gethashcode-different-each-time-i… )
The original problem is using linked lists to handle hash collisions. Assuming this is what you want (to keep all values rather than discarding old values, like e.g. Python's dict objects do) obviously you should use a data structure that can handle the case of lots of collisions well, or check your user input.
At the very least the function should have a name that reflects its behaviour, eh? "GetUnguessableHashCode()" or something?
This reminds me of the recent fiasco over in Python land where somebody noticed that int() called on large strings can block the interpreter. The obvious solution is to add an optional timeout parameter (the problem is in the time domain after all.) Instead they added a limit to the size of strings you can pass to int()!