Khi phát triển phần mềm việc chia nhánh để phát triển độc lập, song song luôn xảy ra. Có nhánh xong trước, có nhánh sẽ hoàn thành sau. Làm sau để các nhánh chưa hoàn thành có thể có những tính năng từ nhánh chính (nhánh master) là vấn đề của bài viết này.
Kịch bản cụ thể như sau. Có 2 tính năng phát triển độc lập với nhau, theo lẽ đương nhiên, lập trình viên sẽ tạo ra 2 nhánh riêng biệt từ nhánh master. Hai nhánh này sẽ có tên lần lượt là
feature-1
feature-2
Nhánh feature-1 hoàn thành sớm và nhanh chóng merge vào master. Lúc này nhánh master đang có mã nguồn mới nhất từ nhánh feature-1. Vấn đề bây giờ đó là ở nhánh feature-2, nhánh feature-2 hiện tại chưa phát triển xong, tuy nhiên nhánh feature-2 muốn có các tính năng mới nhất mà hiện tại đang có ở nhánh master.
Sẽ có 2 cách làm trong kịch bản này:
Merge từ nhánh master qua nhánh feature-2
Rebase nhánh feature-2 đến nhánh master
Rebase dịch sang tiếng việt có nghĩa là chuyển nền, còn có thể hiểu cách khác là chuyển commit nguồn của một nhánh sang một commit khác.
Lưu ý là nhánh master đang nói ở đây cụ thể là điểm commit mới nhất, cuối cùng trên nhánh master.
Một lần nữa, vấn đề hiện tại đó là làm sao để nhánh feature-2 có các tính năng mới nhất từ nhánh master
và rồi lập trình viên có thể phát triển tiếp trên nhánh feature-2.
II. Giải pháp
1. Merge từ nhánh master qua nhánh feature-2
2. Rebase nhánh feature-2 qua nhánh master
Có thể nhận ra điểm khác biệt ngay lập tức đó là nhánh feature-2 được phát triển dựa vào commit màu xanh dương thay vì là màu xanh lá.
III. Ưu & Nhược Điểm.
1. Merge từ nhánh master qua nhánh feature-2
Ưu điểm: Nhìn rõ các commit lịch sử của nhánh feature-2, từng commit lúc này hoàn toàn ko có dính dáng gì đến commit mới nhất thuộc nhánh master2. Khi áp dụng giải pháp này, giả sử muốn quay lại các commit cũ thuộc nhánh feature-2, hoàn toàn là điểu dễ dàng, mã nguồn hoàn toàn không dính dáng gì đến nhánh feature-1 hết.
Nhược điểm: Git log nhìn sẽ rất xấu.
2. Rebase nhánh feature-2 sang commit mới nhất thuộc nhánh master
Ưu điểm: Git log nhìn sẽ cực kì, cực kì đẹp.
Nhược điểm: Các commit cũ của nhánh feature-2 lúc nhánh này dựa trên commit cũ thuộc nhánh master sẽ bị biến mất trên git log. Thay vào đó, các commit thuộc nhánh feature-2 sẽ hoàn toàn dựa trên commit mới nhất thuộc nhánh master. Giả sử như muốn quay lại các commit cũ, mã nguồn không dính dáng gì đến mã nguồn của feature-1, để làm được việc này khó khăn hơn rất nhiều so với phương pháp merge.
Khi merge hai branch với nhau, có những kiểu merge như sau
no fast forward: không chuyển tiếp nhanh
fast forward: chuyển tiếp nhanh
squash: nén 🏋️
2. Chi tiết từng loại merge
a. No Fast Forward (–no-ff)
Khi merge ở chế độ no fast forward, một commit merge sẽ được tạo ra trên git log cho dù khi merge có xảy ra conflict hay không. Đây là sở đồ khối khi áp dụng cách merge no fast forward
Lưu ý là sự khác nhau giữa các loại merge là ở commit merge cuối cùng (màu hồng)
Như ở trên sơ đồ khối, sự thay đổi của của nhánh(branch) tồn tại ở trên (B1, B2, B3), điểm cuối cùng (màu hồng) thực chất không có chứa thay đổi gì cả, ngoài trừ việc lưu ý rằng đây là commit merge từ nhánh có tên là branch vào nhánh master.
b. Fast Forward (–ff-only)
Khi merge ở chế độ fast forward, các commit từ nhánh mới sẽ chuyển tiếp qua nhánh đích và không có merge commit được tạo ra. Đây là sơ đồ khối các branch trước khi merge, không có commit màu hồng như đồ thị dành cho --no-fast-forward
Và đây là sơ đồ khối sau khi merge từ nhánh branch qua master
Như trong hình vẽ, nếu áp dụng fast forward, hoàn toàn không có merge commit như là no fast forward
c. Squash (–squash)
Squash có nghĩa là đè nén. Khi merge theo kiểu squash tất cả các commit thuộc nhánh sẽ bị nén với nhau lại sau đó merge vào nhánh đích. Đây là sơ đồ khối trước khi áp dụng merge squash (nó giống như là hình trước khi merge theo kiểu fast forward merge.
Còn đây là sơ đồ khối sau khi merge theo kiểu squash.
Như trong sơ đồ khối trên, sau khi merge theo kiểu squash, tất cả thay đổi trong các commit (B1, B2, B3) đều được nén lại thành một commit duy nhất (màu hồng). Khi mở git log của master, người xem sẽ chỉ thấy có commit đã nén mà ko thấy các commit (B1, B2, B3).
3. Ưu điểm và nhược điểm
a. Fast Forward
Ưu Điểm:
Khi nhìn vào git log ở nhánh bị merge vào, người xem sẽ thấy toàn bộ các commit ở trên nhánh gốc. Thêm vào đó, ở trên git log chúng ta sẽ thấy một đường thẳng. Việc sử dụng fast forward cực kì có ích khi ở trên branch bị merge, không có tồn tại thêm các commit mới, lúc này áp dụng fast forward dòng git log là một đường thẳng.
Nhược Điểm:
Khi áp dụng cách này, khi muốn biết là cái commit được tạo ra trên branch nào, khi này sẽ gặp khó khăn khi nhìn trên git log. Đây là hình ảnh lấy ra từ git log--graph khi áp dụng git merge --fast-forward
b. No Fast Forward
Ưu Điểm:
Cũng giống như là fast forward, người xem sẽ thấy toàn bộ commit của branch nhánh khi học xem git log. Thêm vào đó, người dùng còn biết được chính xác là commit được phát triển trên nhánh nào. Ưu điểm cuối cùng là khi nhìn git log--graph đẹp. Đây là hình ảnh ví dụ khi áp dụng git merge--no-ff.
Nhược Điểm:
Giả sử với một người phát triển phần mềm và commit liên tục, một chuỗi các commit nhỏ nhỏ xuất hiện trên git log kết quả là nhìn rất rất là không đẹp, những commit nhỏ nhỏ đó nên được nhóm lại thành một commit.
c. Squash
Ưu Điểm:
Khi nhìn vào git log, sẽ thấy git log cực kì sạch sẽ. Khi phát triển phần mềm, luôn luôn tồn tại những commit có message ít ý nghĩa, khi nhìn vào git log và đọc git message, thấy rất có vấn đề. Đặc biệt là những lập trình viên code và commit liên tục.
Nhược điểm:
Cực kì sạch sẽ quá cũng là vấn đề. Giả sử đó là một chuỗi commit, khi tìm cách debug theo brach ví dụ sử dụng git bisect , nhìn một cái commit đơn độc cũng khá là mệt.
Sometime in my life, I want to share something stupid anonymously, somewhere to store data anonymously. Imgur is good, but I am not that bad to abuse the Imgur, last year, they close the api to share image anonymously and I dont want to do some shit crawling stuffs or playing around with their website.I write my own image data storage. The project written in elixir with phoenix web framework supporting and foundation. You can access the projet at http://image.hexalink.xyz
This small web application which helps you to share your images easily and quickly. Those uploading images might be stored on the system until my server storage getting full. If the server’s full, images will be removed to save space.
It’s general and popular to find min/max value of a column in tables with aggregate functions such as min and max.
However, I would like to use vanila way to solve this problem, in addition to explain how does it work with join.
The explaination can help you get a abstract of join and how does it work in processing.
Issue
To help you understand how join can help you approach min and max, we need a good example. Now let start. We got
alot of people in a company, each of them has more then one assessment during their work time. The question is how to
get the latest, newest assessment and the first, oldest assessment. The big question is how to get the latest
and the first assessment answers filter by that person and assessment, remember that an assessment can be done many times. Our table will look like:
Thinking approach
To find min/max value of inserted_at value filtered by the person_id and assessment_id, first we need to find all record filtered by person_id and assessment_id, then we must find a min/value of inserted_at via a loop to comparing one to others inserted_at siblings, one which is smaller than others is the smallest and one which is greater than all others is the greatest. This also can be understand in this way.
If you can find a group named A from a fixed set filtered by some conditions, all elements in this group A can find a greater element from a fix set. On the other hands, other elements which does not belong to the group A cannot find any element which is greater than itself, which also means that those other element are the greatest.
If you can find a group named B from a fixed set filtered by some conditions, all elemments in this group B can find a smaller element from a fix set. On the other hands, other elements which does not belong to the group B cannot find any element which is smaller than itself, which also mean that those elements are the smallest.
Solution
I would like to find the latest/newest assessments of all people. Let do it step by step and analyze:
The over all data set of a person who own id is 1. As you can see, for a single person, there are many assessments has been done by him/her. We have to find out the latest assessment answers of each assessment id. For example: assessment answers with id: 1, 7, 8, 9; the person has finished this assessment_id 2 four times.
Now, let find a group of element which can find a greater one among the fixed set. The comparing value based on inserted_at column.
The fixed set we are talking about is starting from id 1 -> 12, however, our group contain 1, 7, 8, 10. 1, 7, 8, 10 can find greater element for instance:
The inserted_at(id_1) is smaller than inserted_at(id_7). For those elements which does not belong to this group cannot find greater element, because they are greatest ones. The other elements should include 2, 3, 4, 5, 6, 9, 11, 12. The previous query used join phrase as a consequence, it remove all unsatisfied element for condition aa.insrted_at < ab.inserted_at. On the other hands, left join takes satisfied and unsatisfied records.
Now let check the id of assessment answers records if the id 2, 3, 4, 5, 6, 7, 9, 11, 12 are the greatest. They cannot find any greater elements.
Let finalize our works to extract the greatest element only
And for short, here it’s final shot to find the latest/newest assessment answers of user(id: 1)
To find the smallest value, here is your solution:
Quesions
Q: Can we place the condition aa.inserted_at < ab.inserted_at under where phrase instead of under lelft join on phrase, and why?
A: No, if we put the condition aa.inserted_at < ab.inserted_at under the where phrase, we can only get a group of not-greatest elements
Q: If I use left join in this query, why dont I get a combine of satisfied and unsatisfied records:
A: This is how the query look like and its result set.
The condition I am talking here is aa.person_id = ab.person_id and aa.assessment_id = ab.assessment_id
Satisfied condition is aa.person_id == ab.person_id and aa.assessment_id == ab.assessment_id
Unsatisfied condition is aa.person_id != ab.person_id or aa.assessment_id != ab.assessment_id
Why the record that are not satisfied exist in the result set. Hmm, that’s a question I am think about. Personally, I think the developers of postgres did make an exception, hardcode perhap if people use equal in the join expression.
Since the documentation of Opera has been out of date, this article is all about installing flash plugin manually, I strongly believe that this can help you in any version of Opera or any operating system. In my free time, I have spent time researching on the resouce files of Opera and trace the directory that Opera use to read the flashplayer.so.
As you can guess, we gonna download flash plugin from its official site then extract into any of these directory such as /usr/lib/adobe-flashplugin/. You need to extract two files including libpepflashplayer.so and manifiest.json, it’s a must to copy manifest.json along with the libpepflashplayer.so. Remember to set extracted files with appropriate permission (chmod command).
1. How to specify the layout when render() in controllers
There is an option in render/3 method, source
In the below example, I did specify the layout, the layout will be located at @conn.assigns[:layout], so as :id
The directory which locate layout look like:
2. Setup a default layout for all method within a controller
We have to use plug :put_layout.
3. Get advanced from PLUG.
Because of using plug, we can also specify the defaul layout in router. In route.ex we can define an extra pipeline.
And then, within scope, add the pipeline via pipe_through. Here is an example.