WEBVTT 00:00.000 --> 00:13.400 Hello everyone, please welcome our next speaker, Vladislav, he will talk on efficient 00:13.400 --> 00:24.160 to get work flow for high stakes projects. 00:24.160 --> 00:30.800 One, one, checking the microphone, hello everyone, thank you for coming, a lot of great 00:30.800 --> 00:35.200 people today who open source community, I absolutely love it. 00:35.200 --> 00:43.160 So as was said, my name is Vlad, I am working in open source and appropriate proprietary 00:43.160 --> 00:48.400 development for about 12 years already by now, time is flying. 00:48.400 --> 00:54.680 And most of the time I spent working on databases, closed source open source, game development 00:54.680 --> 01:03.160 and right now in advertisement technology and today I wanted to present you some strategies 01:03.160 --> 01:09.400 of using Git that I found particularly helpful in my kind of work, in very specific conditions 01:09.400 --> 01:15.720 in which I was working my entire career and I mean projects which are big, they live long 01:15.720 --> 01:22.840 enough and it costs a lot to do anything wrong in them, that's why it's high stakes. 01:22.840 --> 01:29.080 And I want to emphasize firstly, like this disclaimer, there is no one right way to do 01:29.080 --> 01:34.120 Git, I am perfectly aware it's a very sensitive personal topic for a lot of people, what 01:34.120 --> 01:41.360 is right, what is wrong and I do not claim my today's points to be the absolute truth, 01:41.360 --> 01:46.520 it always depends on the project and even on people working on that project. 01:46.520 --> 01:53.200 So I'm just presenting one of the ways that I found is very useful in my specific context 01:53.200 --> 01:59.080 and I'm just hoping that you will keep an open mind, you maybe will try some of the stuff 01:59.080 --> 02:03.760 I will be showing, it long have to take it all at once, it's not a complete, like 02:03.760 --> 02:09.480 a modeling framework, you can just take some specific cheery pick, git cheery pick, some specific 02:09.480 --> 02:15.760 points out of it which you will find interesting useful for yourself and just keep an open 02:15.760 --> 02:17.760 mind. 02:17.760 --> 02:25.240 So most beneficial my presentation will be by the way to firstly students, juniors who are in the 02:25.240 --> 02:31.160 beginning of their career and they see a lot of ways to do version control, a lot of different 02:31.160 --> 02:38.120 ways inside every tool and they like feel maybe a bit lost, what is right to do, which 02:38.120 --> 02:43.960 tools are useful for what I hope, at least for Git, I can show you one of the ways which 02:43.960 --> 02:50.240 I believe probably was how it was supposed to be used and also for senior and lead developers 02:50.240 --> 02:58.880 as well who have pains in maintenance of their high stakes projects like to keep it clean. 02:58.880 --> 03:05.120 Our presentation today will follow this plan, first I will present you my context, like 03:05.120 --> 03:10.120 how it looks like, actually what I have to deal with every day, so maybe then you all 03:10.120 --> 03:17.280 better understand why certain things I propose to do in a specific way, then I will present 03:17.280 --> 03:26.120 you the points of my this efficient workflow, then I will show you benchmarks of git usage 03:26.120 --> 03:31.600 in the end to see how what effects you can get when you get it applied in real project 03:31.600 --> 03:37.880 with real people, like what people said when they try it what I propose and then we will 03:37.880 --> 03:45.040 make a short conclusion, this QR code right now is this link will not work after the presentation 03:45.040 --> 03:49.920 I will open it online and you will by the same link will be able to see it, so you can 03:49.920 --> 03:58.120 as well say it now, I will also show it again in the end, so the ways of Git they obviously 03:58.120 --> 04:04.520 highly depend on the type of project and people working on that project, there are like 04:04.520 --> 04:09.000 maybe infinite number of projects and people were using them in different ways but I was 04:09.000 --> 04:15.640 able I think to find free types which kind of allow to like almost every project you could 04:15.640 --> 04:22.880 put into one of those free categories, roughly speaking, first one we can call like enterprise 04:22.880 --> 04:28.360 it's usually something big, closed source, it might be not even in IT company like it 04:28.360 --> 04:34.800 could be a bank or something like this and they have a lot of people, a lot of code, old 04:34.800 --> 04:40.720 code, they have complicated processes how stuff is supposed to be done and they maybe use 04:40.720 --> 04:46.600 Git for like hooks, CI, CD but that's all, otherwise Git for such projects, typically 04:46.600 --> 04:50.680 from what I have seen is just a distributed code storage, they don't care if it's Git or 04:50.680 --> 04:56.960 whatever else, as long as you can hook CI, CD on it, they are good for them, need this 04:56.960 --> 05:01.680 to say that they don't care about Git history, clean cleanness of chemists or anything 05:01.680 --> 05:06.960 like that, probably this will not be very beneficial for them, another type we could call 05:06.960 --> 05:12.480 it a startup, it's similar to enterprise in a way that they also don't care too much about 05:12.480 --> 05:19.080 Git history or chemists because they move fast, they throw things out like throw things 05:19.080 --> 05:25.680 away, open, so keeping Git history doesn't make much sense, they will throw it away eventually 05:25.680 --> 05:30.520 anyway and there isn't even much to keep since and you'll start up right, team a small 05:30.520 --> 05:34.040 they are easily communicating with each other, a green one, things they don't need 05:34.040 --> 05:39.400 the stick procedures again, here Git is more like a distributed code storage, the last 05:39.400 --> 05:47.480 time though, it's a product, it's an open source, quite often, can also be closed source 05:47.480 --> 05:53.000 but more often it's making sense for open source, where you have middle size project, middle 05:53.000 --> 05:58.880 size team is not very frequently, chemists are being made like maybe at every hour on 05:58.880 --> 06:04.360 hot days but unlikely more than that, and the project is much more, it tends to leave 06:04.360 --> 06:12.200 long, it already leaves long, you can imagine like years, tens of years for more and it 06:12.200 --> 06:18.480 is also high stakes, meaning that cost of mistakes is very expensive, financial and 06:18.480 --> 06:22.800 repelational for the company, so you need to be very careful when you commit something 06:22.800 --> 06:27.800 into such projects, it might affect actual clients who are paying to you and you're very 06:27.840 --> 06:33.960 careful what you do, my talk is targeting the last one, the other ones might also find 06:33.960 --> 06:39.600 that useful but from experience it's in enterprise, you sometimes just cannot do things 06:39.600 --> 06:45.680 and start up they might not need those things but for product it will make all the sense, 06:45.680 --> 06:52.480 before we proceed I will show you a bit a little bit glimpse into my context in which 06:52.520 --> 06:58.160 I am operating, so it will be easier to for you a whole I hope to understand the following 06:58.160 --> 07:07.800 things, firstly I write code exclusively CNC++ which means it's well firstly it's very fast 07:07.800 --> 07:17.560 and nice low level fast company but yeah might be the short what I said, but also we do 07:17.560 --> 07:23.040 have problems like especially C++ is hard to cook it right, you can cook it right but 07:23.040 --> 07:27.480 it's very hard to do, one thousand different ways to do the same thing and you will have 07:27.480 --> 07:32.120 all sorts of issues, a runtime which you need to take care of compiler will not help you 07:32.120 --> 07:39.560 like memory leaks, data corruption, triads, racing, it's actually you need to keep to be 07:39.560 --> 07:45.200 alert all the time, also code size will be starting from hundreds of thousands of lines of 07:45.240 --> 07:53.440 code going over millions and really large projects and the code is old, my current code 07:53.440 --> 08:00.240 base it's over 20 years old which means it contains every single C++ standard that 08:00.240 --> 08:05.840 came out for all together, it's not like we're moving to next one they move all the 08:05.840 --> 08:13.120 old stuff, it also means that authors of this code are gone like they're not there, you 08:13.200 --> 08:19.040 can not ask them anything anymore, that's the main problem of the age of such project 08:19.040 --> 08:24.880 and you have a lot of legacy, somebody did it, you don't know what it is, why, how it works 08:24.880 --> 08:32.880 but it works, there is nobody to ask, and also call this high in every sense like it's 08:32.880 --> 08:39.680 high load, it's high scale like large scale and it's high stakes, to give you an example 08:39.680 --> 08:47.440 of high load like you add one byte to a struct, you think like it's not a big deal, it gets deployed 08:47.440 --> 08:53.040 on one of the clients, they get explosion of hundreds of gigabytes in a cluster for one byte in one 08:53.040 --> 08:59.280 structure or you add accidentally or you just decided it doesn't matter, code makes, it becomes 08:59.280 --> 09:04.240 simpler, you add it like a hundred microseconds load down, one millisecond load down on a hot path 09:05.040 --> 09:10.080 and then in the end of the month you will receive report from the client that every day during 09:10.080 --> 09:16.240 that month you had a opportunity to cost because of that tens of thousands of euros per day, 09:16.240 --> 09:23.600 this is what I mean as high stakes and high load, from all this I have concluded the two big 09:23.600 --> 09:31.360 points, firstly you cannot rely on people because they will like in the short one they will 09:32.320 --> 09:37.920 they will retire, they will burn out, they will be on vacation and suddenly you need to deal with 09:37.920 --> 09:43.680 an incident and they are not responding or they like literally move on to the next world so 09:43.680 --> 09:51.920 to say you cannot ask them, which means you need to rely on the code, code is the truth, 09:53.280 --> 09:57.440 what is written and the code is what will be running, some people might even be in the team 09:57.440 --> 10:02.400 and tell you what they think it's what how it's running but it might be not how it's running so 10:02.400 --> 10:08.400 code is the only source of truth, you must rely on it, you must keep it clean so it's readable and 10:08.400 --> 10:14.960 maintainable and story of that code so you can see how it was evolving and it will help you 10:15.760 --> 10:20.960 in the future and all of those points will be presenting next I wanted to unite and there's some 10:20.960 --> 10:27.200 catching name so it would not be just a bunch of like a pile of recommendations, I decided to call 10:27.200 --> 10:36.240 a Tatonic Flow similar to like git flow, one flow, this is atomic flow, this is like we will start 10:36.240 --> 10:43.040 with the most basic thing, it's most important point of my whole presentation, I show it first 10:43.040 --> 10:49.520 so you are still not too tired by the end of the presentation, if you get just this thing right, 10:49.600 --> 10:55.360 I will be already very happy and this third point is that commit should be atomic, 10:56.000 --> 11:02.960 hence is the name of the flow, atomic flow, this consists of several things, what does it mean atomic? 11:03.600 --> 11:12.320 In projects I work on, it's often very helpful when I can, for any line of code, tell why it was done, 11:12.960 --> 11:18.800 the key point is why, not what, what is done, I see it's the code, code is what, 11:18.800 --> 11:23.680 I can read it perfectly find myself, I don't need it narrated somewhere in the commit message 11:23.680 --> 11:29.200 or in the comment, like LLM's write, like to use those narrative comments all over the place, 11:30.160 --> 11:37.840 I need the why and the why, it's quite often noted in the code, for example why would we need it, 11:37.840 --> 11:43.680 imagine, I know there is a bug somewhere in some function, somehow I know it's in one function 11:44.640 --> 11:50.560 and then knowing the reason for the function's latest change, like in my case in 90% of cases, 11:52.400 --> 11:56.800 I know there is a bug in a function, I open it's latest commit, I see the bug instantly, 11:56.800 --> 12:02.160 like on review, maybe it was missed, you didn't know this was possible, then you deployed on 12:02.160 --> 12:06.720 production, it breaks, you open the commit and you see I, yes, how, this is how it would break, 12:07.920 --> 12:14.480 so I see the latest change and it gives me, can, can give me the, quite often, the answer, what 12:14.480 --> 12:23.280 went wrong and it would also help me extremely much, if the commit is small, imagine you found 12:23.280 --> 12:28.720 that commit, it touched the function like literally two lines of change and you like scroll through the 12:28.720 --> 12:34.160 commit, that's it another thousand lines of change, some code being moved, some other features 12:34.160 --> 12:39.200 being done, some bug fixes in the same commit, now you are not sure if this commit is at fault, 12:39.200 --> 12:44.000 like if this place is at fault, maybe the problem is somewhere else in the same commit, 12:45.040 --> 12:51.520 so it would be very helpful if this commit is small and is doing one thing in this one place, 12:51.520 --> 12:56.720 then it's less cognitive load for me to understand the, notice the bug, those two things, 12:57.520 --> 13:05.840 the ability to quickly see the why behind any change and the ability to understand that first 13:05.840 --> 13:14.480 from its small scope form the atomic commit, atomic like it's also the name is kind of self-explaning, 13:14.480 --> 13:21.120 right, the atomicity what does it mean in this case commit is self-sufficient, so it's alone, 13:21.120 --> 13:28.320 this commit is already functional unit of your code, it's self-explaning, doesn't need any other 13:28.320 --> 13:36.320 commits to be understandable, it brings value to the code and nothing can be removed from it without 13:36.320 --> 13:42.960 breaking it and nothing needs to be added to keep it stable, so it's like an atom, a stable unit 13:42.960 --> 13:50.320 of like your code evolution, it might still sound too abstract but think of it in another way, 13:50.400 --> 13:55.600 think of commit as functions, commit's are actually functions because functions are doing what, 13:55.600 --> 14:02.160 they take input, do something with it, produce output, commit does the same input of your commit as your 14:02.160 --> 14:10.320 old code base, by the of the function is the div, name of the function, is git commit, git message, 14:10.320 --> 14:16.880 and the title, output is the new version of your code and then it all makes sense, right, 14:17.040 --> 14:23.600 functions are supposed to be small, do one logical thing, be self-sufficient and understandable 14:23.600 --> 14:29.680 from their name, treat commits like this as well and then it's very easy to understand the reason why 14:29.680 --> 14:36.880 it can be useful, let's see some examples, this is a commit, real one, do not read the small text, 14:36.880 --> 14:44.000 I made it small intentionally, you don't need to read my slides, just look at, yeah, it also you can 14:44.000 --> 14:49.280 click on this link when you get the slides to see the original commit, it will be available in all 14:49.280 --> 14:57.040 examples, those links, so just pay attention to this, it's very small, it's like 11 lines of functional 14:57.040 --> 15:06.400 changes and some text, it fixes one bug, a crash and it's clearly visible from the title, 15:06.400 --> 15:12.000 then it does nothing else, explanation why, how did this bug happen, how did we miss it, 15:12.080 --> 15:17.440 what was the reason it's in those two paragraphs of text, very nice, easy to review, 15:18.640 --> 15:24.560 very clear to review and you'll also mention a stick at number, so if some context is not enough, 15:25.520 --> 15:29.680 the person can open the ticket number and see some may be a discussion or a history of 15:29.680 --> 15:35.280 older changes and times to fix it, can be very helpful, this was the previous version of the same commit, 15:35.280 --> 15:42.000 which was rejected, because firstly, what is it doing like, is it a performance regression, 15:42.000 --> 15:49.760 is it a crash fix, is it a logical issue being fixed, I have no idea, it says fix, what does it fix, 15:49.760 --> 15:57.520 I don't understand, don't see pipe push like, what happens if I push, and the commit message is empty, 15:57.520 --> 16:02.560 there is absolutely nothing and the commit is bigger, it has 15 lines, you know why, 16:02.640 --> 16:08.080 because the person who created it, didn't want to write a test, and decided just in case 16:08.880 --> 16:14.560 hack the same fix in multiple places, thinking that they might also break, but it was completely 16:14.560 --> 16:25.680 unnecessary, the original real fix like it's actually even 10 lines, 11, 11 works, another example, 16:26.400 --> 16:31.680 look at this mere chick quest, again you don't need to read everything, just look at the size, 16:31.760 --> 16:39.520 it's 15 commits, it's doing one thing though, it's not 15 different things, it's 15 steps 16:39.520 --> 16:46.640 of one, I think, in this case, bug fix, yes, and the average size of every commit is 50 lines, 16:48.400 --> 16:54.080 so the all fix the same bug, those commits is just, there was one bug, which was manifesting 16:54.080 --> 16:59.760 itself with multiple different places of the code base, unrelated places, but same bug, 16:59.920 --> 17:06.480 and we decided to fix this in one virtual quest, in multiple small commits, every commit with a test, 17:06.480 --> 17:10.800 fixes one place, the every commit is reviewable, deployable, and everything, 17:12.240 --> 17:19.360 and this is easy to review, like one commit, 50 lines just do it for every commit, and they have 17:19.360 --> 17:26.480 used them, if I would not care about commits, this would be over 1000 lines, which somebody would 17:26.480 --> 17:34.800 have to review all at once, and spot their 7 different places which were fixed, this is quite 17:34.800 --> 17:40.800 lot of work for review, including yourself, because first review you will be a self-review, obviously, 17:40.800 --> 17:48.480 before you submit it to somebody else, another example, a bit extreme, but still interesting to look at, 17:48.480 --> 17:54.960 it's one line change, 21 lines of explanation why this needs to be done, 17:56.560 --> 18:01.440 the question is why not put it in the code, this comment in this case it's specific to that 18:01.440 --> 18:07.600 commit, because this was a compilation fix, on the you can pileers, this bug didn't exist, 18:07.600 --> 18:14.000 on old can pileers, it would not come by also, you kind of could not miss it, and this message 18:14.000 --> 18:19.600 was for a review, really, not for the code maintenance, but still, it was very easy to review, 18:20.160 --> 18:24.480 you don't even need to contact the person who wrote this commit, it's just all right there, 18:25.120 --> 18:30.800 right in the text, from the commit, I miss it, you probably have already deduced that, 18:30.800 --> 18:36.560 if you do it the way I proposed, then any non-trivial merge request will require more than one 18:36.560 --> 18:40.880 can it, it's actually not very often when you can't get away with just single commit, 18:41.600 --> 18:50.000 on something untrivial, quite often you will need to do, you will need to touch surrounding code, 18:50.000 --> 18:57.520 prepare some base for your functional change, maybe move some code around, rename variables, 18:57.520 --> 19:02.320 functions, extract, code from one function to multiple other functions, right there, this like 19:04.560 --> 19:10.960 cleaning before you do the actual change, it can be actually extracted into separate committees, 19:10.960 --> 19:17.520 and to work with that, when you introduce the next concept, the daily work must be organized 19:17.760 --> 19:21.760 in so-called purchases or changes list or call it whatever you want, 19:23.760 --> 19:29.440 usually when you do it like this, you do multiple commits from top of each other in the beginning, 19:29.440 --> 19:35.440 which do the preparation, like some commits first, you will move code from one file to another, 19:35.440 --> 19:40.880 some commits will do rename throughout the whole code base, some commit will add the flag to some 19:40.880 --> 19:46.240 function and everywhere pass it as follows, so like in the next commit you can in some cases start 19:46.240 --> 19:51.920 passing it as true, those kind of like preparatory changes, which have no functional value, 19:51.920 --> 19:59.040 but they are needed to make the functional change later, this will firstly keep your, 19:59.040 --> 20:05.680 obviously history clean, secondly it also incredibly helps on the review, because the reviewer 20:05.680 --> 20:11.200 will be able to quickly go from the refactoring noise, it will be easy to review, right, you can 20:11.200 --> 20:17.200 you could move like 5,000 lines of code from one file to another, you will review it like just scroll through, 20:18.320 --> 20:22.560 or you even just look that the file names are okay, and then you don't need to look at the code, 20:22.560 --> 20:29.760 which is moved completely unchanged, right, those large commits can be easy to review, or a commit 20:29.760 --> 20:36.400 changes like 1,000 different lines, but all of them is a function rename, again the reviewer will just scroll 20:36.480 --> 20:41.840 for those changes easy without spending too much cognitive effort on this, but then reviewer 20:41.840 --> 20:49.520 issues the last commit, small functional atomic changes, and reviewer can spot issues in those changes 20:49.520 --> 20:55.120 easier because they are smaller, it's less context to keep it in mind than you can notice issues 20:55.120 --> 21:00.880 much easier, they will be more on the spot, but they will not be hiding in the huge pile of refactoring 21:00.880 --> 21:09.280 noise, right, let's see some examples, again this one will already show, it's a merge request, 21:09.280 --> 21:19.040 which fixes one bug in 7 different places, so it's 7 functional commits, small ones, and 8 commits, 21:19.040 --> 21:25.360 do preparatory refactoring can benchmark, they're extremely easy to review, those other 8 commits, 21:25.440 --> 21:31.840 it was like 50% of the complexity you cut away and make it very easy to review, and then the 21:31.840 --> 21:39.920 reviewer reviewer becomes faster and higher quality, reviewer will easier find problems in your work, 21:41.040 --> 21:46.640 and highlight them, this, imagine it would look like this, like you have commits, address, 21:46.640 --> 21:52.480 merge request comments, review fixes, benefits the IP, all this stuff, it's unreviewable, 21:52.560 --> 21:59.840 who are able to review the right side, will have to review it all at once, they will have no choice, 21:59.840 --> 22:04.320 reviewing this crap, it's one by one, those commits are on the review under reviewable, 22:06.000 --> 22:12.720 another example, also a bit extreme, but it shows the point well, it's 25 commits in one merge request, 22:13.280 --> 22:20.160 2,400 lines of changes without even tests, with test it's twice more, it was a very large 22:20.240 --> 22:26.320 single feature, which consists of multiple different parts, and on which I had to spend like a couple 22:26.320 --> 22:32.160 of months, I think, but it was actually very easy to review, because you know what, every commit, 22:32.160 --> 22:41.280 maximum was 350 lines, and more than half of the changes are refactoring, like preparatory changes, 22:41.280 --> 22:49.280 which were also very easy to review, another example, the latest one, also I like it a lot because 22:49.440 --> 22:54.400 shows how important it is to split code moves into separate commits, I heard the merge request 22:54.400 --> 23:05.280 with 14 commits, 3,300 lines of C code changed, but 2,500 of them were one commit, where code was moved 23:05.280 --> 23:11.360 unchanged, and reviewer can just go for that commit like in one minute, and then concentrate on 23:11.360 --> 23:18.080 small 13 remaining commits, and actually it helped us to find a few issues which I fixed, 23:19.040 --> 23:24.160 in the first round, I have to admit I was lazy, I did it in one commit, but then on review, 23:24.160 --> 23:29.280 I was told like, no, you have to split it, and then yeah, it actually helped. 23:31.360 --> 23:35.840 Technically, the previous points already make a huge difference, some people can even stop at that, 23:35.840 --> 23:40.400 like you can just take commit that a missity, or you can take commit that a missity and patch sets, 23:40.400 --> 23:45.520 but if you want more, there is actually more, which can help you even further, not even during 23:45.520 --> 23:55.200 development, but already during deployments and incident investigations, and I propose to keep 23:55.200 --> 24:04.560 Git history linear like one line. It means that when you look at Gitlog, or Gitlog is about 24:04.560 --> 24:10.560 example, I always align, but when you build a Git graph like, or you use UI for Git like Gitcrack and 24:10.560 --> 24:16.080 or whatever, you in projects sometimes see like there is a lot of parallel branches, 24:16.080 --> 24:22.240 somehow intersecting with each other, right? I propose even in those UI's, let's keep our history clean, 24:22.240 --> 24:29.120 one line. You still have development branches, don't take Gitmer on, like I don't suppose to 24:29.120 --> 24:35.200 have one branch, like for instance, per force version control system, it has no branches, like 24:35.280 --> 24:41.040 you do one commit and you need to merge it, there's no branches, but I still work on development 24:41.040 --> 24:47.440 branches, but the main branch development develop main master whatever it's, one line. 24:49.040 --> 24:53.280 You can even still have merge commits, it's just they will be also on the line, and they will be 24:53.280 --> 25:00.160 empty by the way, because you will have no conflicts. Imagine it's possible, imagine it's easily 25:00.240 --> 25:05.760 achievable. Let's see what we could get from that if it would be easily possible. 25:06.800 --> 25:12.800 Firstly, each commit on the Gitlog line is going to be right where it was actually applied, 25:12.800 --> 25:20.000 which is not like this when you use merge commits and you merge in your outdated branch into 25:20.000 --> 25:33.120 a branch which went forward. And it gives you 100% possibility to see historically what changes preceded 25:33.120 --> 25:38.960 which changes on your branch. The merge commits, it will not be so easily possible. 25:40.320 --> 25:45.680 Like when you have a graph, you have two parallel branches, how can you say which one was applied 25:45.760 --> 25:53.040 earlier, on the line it's 100% possible. You can also automatically from this, you can check out 25:53.040 --> 25:59.200 Git checkout any point on the line, it will pass test, it will compile, it will be deployable, 25:59.200 --> 26:05.680 and you know what it is going to be helpful for for Git by sect, you can get by sect even your 26:05.680 --> 26:11.920 production release, like imagine you might release, you have two Git tags, and you know this new 26:12.000 --> 26:18.880 release created a bug. Then you do Git by sect, type 1, type 2, you will find one commit which 26:18.880 --> 26:26.080 introduced the bug, you can revert it first and peacefully fix it later. With merge commits again, 26:26.080 --> 26:32.880 it will not be possible unless your history is linear. And then also coming from that, each commit 26:32.880 --> 26:40.000 is going to be transferable. It's a relatively unique use case, but I do have it in my open source 26:40.240 --> 26:47.680 project on which I am working on, but it's not mine. So we do have one long leaving branch, 26:47.680 --> 26:53.840 master branch, we have multiple long leaving branches, one for every long maintenance release, 26:53.840 --> 27:00.400 and we always commit to master first, and then we Git cherry pick to the other older releases where 27:00.400 --> 27:07.760 this fix makes sense. And this is almost always gets applied without any conflicts, we like 27:07.760 --> 27:14.800 literally have it automated in Git Hub CI. You can add a tag in our project like Backport version, 27:14.800 --> 27:20.880 and the bot will cherry pick those commits and merge them automatically. You don't even need human 27:20.880 --> 27:26.800 interaction if CI gets green, it gets merged. And this is because commits are atomic and transferable. 27:28.400 --> 27:34.880 And last but not least is that it's less cognitive load, like developing life of a developer is 27:34.880 --> 27:40.480 complicated enough. And we can simplify it a little bit at least in this case because you can think 27:40.480 --> 27:47.360 of your project as a line as a sequence of versions. It's just easier to think than in terms of 27:47.360 --> 27:52.160 graphs like which branch in parallel with which one was being developed and merged and so on. 27:53.040 --> 27:59.440 I do hope it sounds nice to you as it does to me. And for that to work, we just need one thing. 28:00.320 --> 28:07.200 Your branch is before the merge needs to be based on top of the target branch, like on the picture. 28:07.200 --> 28:12.960 It is so when you do just just did Git checkout minus B, but eventually it will not be so, 28:12.960 --> 28:19.360 because master will go forward, your branch becomes outdated and then like the most frequently used way 28:19.360 --> 28:25.680 is that you click like you type Git merge, it cannot be merged, you have conflict, then you have 28:25.680 --> 28:31.840 to resolve them and you still like Git merge continue, you do Git merge continue and then 28:32.640 --> 28:39.120 what happens is that your commits, the metadata of the commits gets inserted into the history, 28:39.120 --> 28:44.400 but the changes cannot be inserted into history. Your commits are not applied before some other 28:44.400 --> 28:50.800 commits, the changes, they will be all applied on top in this one merge commit. 28:51.360 --> 28:59.840 So, yeah, and you will also have to put all the conflict fixes in this merge commit. 29:00.400 --> 29:06.800 So, if some of your commits were outdated, they will stay outdated in the history and conflict fixes 29:06.800 --> 29:12.080 will be in the merge commit and it can be challenging to fix them all at once because 29:14.160 --> 29:20.000 when you have imagine a very large merge request, many commits, you merge it and you have 29:20.000 --> 29:25.280 multiple conflicts and multiple places of your patch, you will have to fix them all at once, 29:25.280 --> 29:32.160 it might be challenging to do compared to if you had a chance to fix them independently for 29:32.160 --> 29:39.360 every smaller commit. Also, you lose a commit or a miss it because your commits which you just merged 29:39.360 --> 29:45.920 inserted into history, they are not atomic anymore because they do not work without conflict fixes 29:45.920 --> 29:53.920 which are applied later in another commit. And finally, it's even unsafe to do that because when you 29:53.920 --> 30:00.240 imagine you have master brands and your brands, master brands is like it went forward, it has changes 30:00.240 --> 30:05.840 which your brands doesn't have. Your brands has changes that master doesn't have. Both of them can be 30:05.840 --> 30:11.600 green CI. When you merge them, you get a field version which never was running CI, you cannot 30:11.760 --> 30:19.040 be safely sure that it's safe to merge to deploy. So either you like risk it and merge it anyway 30:19.040 --> 30:24.400 or you first merge master into your branch and then merge your branch into master and then you have 30:24.400 --> 30:32.560 two merge commits. There are multiple solutions to that, at least two that I know, first is 30:32.560 --> 30:43.440 squash the commits. It's actually a nice simple way and so it's even available in GitHub and GitLab at 30:43.440 --> 30:49.200 least just like a checkbox and it will automatically squash your commits when you merge them into 30:49.200 --> 30:57.360 master into one commit. Then you do have it's very simple, you have linear history, it's just a little bit 30:57.520 --> 31:03.280 loss of the atomicity but still it's actually a nice simple way to get away with the linear history. 31:04.560 --> 31:12.480 There is another way. The alternative is you need to somehow change the base of your commits. 31:12.480 --> 31:20.640 So they are based on top of the latest master, right? Which means you need to re-based, change the base. 31:20.640 --> 31:26.560 Imagine it was like this, it was outdated and then you change the base and it becomes 31:27.680 --> 31:35.920 one line and then you can finally move it. It's called fast forward merge. So it's a merge, 31:35.920 --> 31:41.360 still but it has no merge commit because it's not needed. There is no conflict. You can just 31:42.080 --> 31:47.040 move your commits on top of the master branch and then it just works. The only problem here 31:47.760 --> 31:53.840 is that you need to learn how to re-based but it's worth it. Like look at my project a couple of years ago. 31:54.800 --> 32:02.560 This is a graph of my git log that I built of the project like it was in state two years ago 32:02.560 --> 32:08.480 before we started using photomic flow. Every vertical line is a merge commit which was applied 32:08.480 --> 32:15.680 later and then the tail goes down to the commits inserted into the history and then I was asking 32:15.680 --> 32:20.880 people how can you work with that and there was one guy who was saying like oh I like it so much 32:20.880 --> 32:26.000 it's so cool. I love merge commit and I was asking him like can you tell me what happened before 32:26.000 --> 32:31.680 what in this and he could not. He's like oh just give me one second just one second and he opens his 32:31.680 --> 32:37.760 git cracking UI and scrolls through all this hell. He couldn't tell me and I don't blame him because 32:37.760 --> 32:44.080 I also cannot read it. It's machine readable maybe but it's I can not read it. And this is how it looks 32:44.080 --> 32:50.720 now. It's a single line. We still have merge commit so I could not like completely destroy them. 32:51.280 --> 32:56.480 We use them on release but otherwise all the development between two releases it's always 32:56.480 --> 33:02.960 a line. Every commit compiles past a test it was at some point on a development branch but then 33:02.960 --> 33:10.320 you merge it is one line. Our team like actually extremely happy right now they previously they 33:10.400 --> 33:18.000 very much were like against it. They were resisting a lot but then eventually when they looked at 33:18.000 --> 33:24.720 how I do it they started using git as well. Now nobody of our team wants to go back ever to this. 33:27.920 --> 33:33.280 And some actual use cases where it helped like it's not just to keep things outestically nice and 33:33.280 --> 33:40.160 beautiful but with no use it has actual uses like free projects which I am working on or 33:40.320 --> 33:45.600 worked at. The freelance project where atomic flow comes from it's a trample database. 33:47.360 --> 33:52.720 They don't even know that they sit on a gold mine like they invented atomic flow. They never 33:52.720 --> 33:59.440 advertised it anywhere but I figured it's it's useful to show to people and the team did just 33:59.440 --> 34:06.400 little bit of statistics 15. Geetrevert calls in last four years just clear geetrevert. No context 34:07.360 --> 34:12.000 commits were in such clean state that you could pick a commit like a year ago 34:12.000 --> 34:18.720 reverted deployed and it works to remove a bag or like whatever or some feature gets deprecated to just 34:18.720 --> 34:25.040 reverted the feature or like sometimes daily sometimes at least weekly. 34:27.280 --> 34:33.040 People create a commit where they reference one or two older commits as and saying like oh here we 34:33.040 --> 34:39.760 do this fix because in some previous commit that was missed and they give a commit hers or like 34:40.800 --> 34:46.080 you like sometimes your reference things or when you work on a feature you can reference previous 34:46.080 --> 34:52.320 attempts to implement this feature in previous commits literally put get get hash in the commit 34:52.320 --> 34:58.000 messes and some UI like GitHub get lab they can even make it clickable they will highlight it 34:58.000 --> 35:04.000 and you can navigate it click by click to see the story of a certain feature or a certain bag 35:04.000 --> 35:12.960 how it was evolving through multiple commits in time. At my current main job we started using 35:12.960 --> 35:18.720 git blame almost daily because as I said we have very old code base we have multiple features 35:18.720 --> 35:24.720 which we don't even know how they work. Nobody touched them like in literally 10 years. You open 35:24.720 --> 35:30.720 some function it was not touched for 10 years. You have nobody to ask for. How it was done you 35:30.720 --> 35:35.280 opened like git blame sometimes you are lucky there is a like ticket number or something. In the 35:35.280 --> 35:43.040 fresh code you always use git blame and find something helpful and we use three simply git by 35:43.040 --> 35:48.880 sect and git revert for two performance degradation rewards very quickly after deployment we were 35:48.960 --> 35:55.760 able to find them with bisect and revert and various bugs in production and in development as 35:55.760 --> 36:00.560 well. Like sometimes you develop a branch you see it's not passing tests you can get bisect 36:00.560 --> 36:05.440 your own development branch to find in which commit you introduce the bug before you have in 36:05.440 --> 36:12.720 the request area and also I worked at the game they have company where investigations using 36:13.600 --> 36:18.560 like they don't use git they use per force but it has something similar to git by sect 36:18.560 --> 36:25.440 git blame and there it was happening daily like every day team over 100 people somebody was using 36:25.440 --> 36:32.560 it to find the reason for a bug or reference something for a new feature or whatever so the principles 36:32.560 --> 36:38.000 they don't just buy just in git is just in git it's very nice to have branches but in per force 36:38.000 --> 36:44.960 for example it also quite applicable so let's assume cleaner history at cool we wanted which means 36:44.960 --> 36:51.440 we want three base and about that I wanted to talk slightly more most of what I agree today is usually 36:51.440 --> 36:56.640 most I talked today is usually agreed with but people are afraid of rebase for some reason even 36:56.640 --> 37:02.880 though it's easier than merge but it's worse when you make your branch you will not get a clean 37:02.880 --> 37:09.280 history right away right you will your branch quite often will look like this like formatting fixed 37:09.280 --> 37:14.880 part one VIP all the stuff and you want to make it nice like ideally you would want to reward 37:14.880 --> 37:20.480 some things maybe squash them together and then suddenly you have a nice have nice commits you 37:20.480 --> 37:27.120 will not get it from the start or like it will be very rare so you usually need to be find the way 37:27.120 --> 37:33.120 to restructure your commits before submitting them for a review and rebase can also help you 37:33.120 --> 37:39.120 even then because rebase it's not just changing the base rebase should is actually re-apply 37:39.120 --> 37:46.800 rebase re-applies the commits on a base that you give it but this base can be anything it doesn't 37:46.800 --> 37:53.680 even have to be another branch you know you can rebase your own branch on yourself on all itself 37:54.080 --> 37:59.200 and for there is a command for that get the base minus i with which you can do quite a lot of stuff 38:00.240 --> 38:06.640 for example take this dirty branch i do a base this branch on itself and minus i it means 38:06.640 --> 38:12.320 interactive it will open text editor of your choice like nano beam or some lime vscode whatever you 38:12.320 --> 38:19.760 can it's configurable where it will show you the plan of rebase every line means like the git 38:19.760 --> 38:25.200 when even you save this file it will apply those commits pick means applying this case 38:25.200 --> 38:30.080 but you can change this plan it's a text editor so you can reorder some lines you can change the 38:30.080 --> 38:34.800 action like you can squash them commits you can change message of some of them you can stop in 38:34.800 --> 38:41.600 between commits and add the new commit there you can delete some commits and then you save it and 38:41.600 --> 38:48.080 git will apply this plan and you will get a nice branch there is obviously much more to say about 38:48.080 --> 38:55.200 rebase i will not be saying more about this but i created tutorial which helps teams to learn rebase 38:55.200 --> 39:00.400 when they never used it before by this link again it's clickable later on the slides for the 39:00.400 --> 39:10.960 is link at the bottom where i created a project with a with a very dirty branch and instructions 39:10.960 --> 39:16.080 how you can turn this branch into a diamond it will look very clean you just follow the steps 39:16.160 --> 39:21.760 where i show you how you can reorder commits add new commits remove commits from the middle of your 39:21.760 --> 39:29.680 branch and so on this was the entire background of atomic flow now a quick through the benchmarks 39:30.960 --> 39:36.160 benchmarks here like i usually do technical presentations where i can benchmark things like 39:36.160 --> 39:42.480 measure latency rps here it's very subjective because it's about people about processes but i 39:42.800 --> 39:49.280 made a survey and i was asking people from different companies different titles what do they think 39:49.280 --> 39:55.040 about specifics like of their daily work with git and starting from juniors to multiple city 39:55.040 --> 40:00.320 who's open source close source project center price start apps products and this is what i 40:00.320 --> 40:08.000 got i will show you a median opinion on every topic that i was a survey firstly how much does it 40:08.000 --> 40:13.920 cost to do atomic flow some people reported like median 10% of development time they spend on 40:14.480 --> 40:20.000 rebase and atomicity polishing but they sounded like a lot to me then i asked how much in minutes 40:20.560 --> 40:27.040 people were able to quantify less than 30 minutes per task people who do it a long time already they say 40:27.040 --> 40:33.360 like one five minutes per task it obviously depends on the size of the change but this is like 40:33.360 --> 40:41.120 median answer it also was reported that atomic flow boosts the project development speed in general because 40:41.120 --> 40:48.560 you might pay if you additional minus direct development but you get an incomparably faster and higher 40:48.560 --> 40:54.320 quality reviews which means you will have less bugs less investigations faster investigations when 40:54.320 --> 41:01.520 you are trapped because of linear history also atomic flow as expected was reported high value for 41:01.520 --> 41:07.120 product but not so for enterprise and startup this is completely understandable as i said my way 41:07.120 --> 41:13.520 is not the most right way is just one of the ways which seems suitable for some products which 41:13.520 --> 41:21.200 reported it as high value then i was particularly interested in speed of reviews and people who 41:21.200 --> 41:26.960 like i had project right now unique situation people were using old ways and switched to atomic 41:27.120 --> 41:32.160 flow and i was asking them how do they feel about reviews now people quantify it all of them 41:32.160 --> 41:38.720 quantified it as faster now but they quantified between one and half to five times faster because of 41:38.720 --> 41:46.800 how much easier it becomes and then i was curious how people review stuff to master price some people 41:46.800 --> 41:51.520 look at whole diff and then at individual commits some people look at individual commits then whole diff 41:51.600 --> 41:58.560 some people do it just this way or just the other way but in the end basically like over 70% of 41:58.560 --> 42:04.800 people do like to look at individual commits when they can also linear history was reported better 42:04.800 --> 42:09.840 in every sense by the reason well when they have when when people have a choice like sometimes you 42:09.840 --> 42:16.560 don't have a choice but people said they would like to use it when they can also to mice for prices 42:16.560 --> 42:21.360 well get blame and get by sector peer to be quite popular tools because i thought always it's like 42:21.360 --> 42:27.040 niche commands but no most of people i asked use them daily or weekly or at least try to use 42:27.840 --> 42:34.560 then i was curious the use of merge commits several people unrelated to each other synchronously 42:34.560 --> 42:42.560 reported to me the same word hate when they were describing how they what did they think about merge 42:42.640 --> 42:48.800 commits this tells you how convenient they are so those are basically where where all the points 42:48.800 --> 42:54.320 i was asking you can take a photo or something on this slide it's like a summary of the whole presentation 42:54.320 --> 43:02.160 you can say to share it when you don't want to scroll for everything i will give you five more seconds 43:02.160 --> 43:09.680 to take a photo then we move on one two three four five you can also likely trope in a 43:09.920 --> 43:16.400 way by the QR code and the short summary again the atomic commits smallest logical unit nothing can 43:16.400 --> 43:21.600 be removed navigate needs to be added patch sets on development branch you deal build a patch set you 43:21.600 --> 43:27.680 sent a review a patch set no single large commit linear history just remove merge commits you will get linear 43:27.680 --> 43:33.440 history as simple as that and interactive rebase is your daily tool to achieve in coldies 43:34.320 --> 43:40.880 the conclusion there is no just atomic flow there is also other ways atomic flow today we focus on 43:40.880 --> 43:47.520 atomicity history reviews and language of the history and project there is also one flow which is 43:48.640 --> 43:56.000 what expired me to do this talk it's built by a guy Adam Ruka and he wrote like some many years ago 43:56.000 --> 44:01.520 he wrote an article basically to summarize how much he hates merge commits and then it evolved in 44:01.520 --> 44:08.640 a series of articles where he designed this one flow of using git it focuses more on simplicity 44:08.640 --> 44:14.320 so prehorse squash for example branching structure like how many actual long-leaving branches 44:14.320 --> 44:20.240 you're supposed to have for what atomic flow doesn't care about that how you should do releases 44:20.240 --> 44:24.480 linearity of the changes and there is of course git flow which tries to do kind of everything 44:24.560 --> 44:32.160 git once and this is why it's differently cooked everywhere this was the end thank you for 44:32.160 --> 44:39.200 your attention again this QR code you can use later to open this presentation 44:40.160 --> 44:55.920 you can connect with me on the like development then professional social networks and 44:55.920 --> 45:02.960 youtube channel where I talk more about system programming, operating systems C and C++