Cách khôi phục database schema nếu gặp conflicts khi rebase
Bài đăng này đã không được cập nhật trong 7 năm
Đây là vấn đề sẽ thường xuyên xảy ra khi làm các dự án Rails
với quy trình làm việc trên branch của git. Giả sử bạn đang làm việc trên một nhánh để phát triển một tính năng nào đó của project. Vấn đề xảy ra khi cả nhánh develop và nhánh của bạn đều chứa file migration, khi đó sẽ xảy ra conflict ở file schema khi bạn rebase, ít nhất là conflict về phiên bản ở đầu file hoặc có thể là conflict ở nhiều chỗ khác nữa. Phiên bản ở đây là một timestamp, tương ứng với timestamp của file cuối cùng được thêm vào trong migration.
Số phiên bản trong file schema cần tương ứng với file migration được tạo ra cuối cùng, là file mà có số timestamp trong tên lớn nhất
Cách giải quyết thông thường
Khi gặp conflict do migration thì sẽ có nhiều người sửa trực tiếp vào file schema.rb
. Việc làm này có khả năng sẽ gây ra trường hợp file schema.rb
sẽ có số version khác với file schema.rb
mà chúng ta tạo ra bằng cách chạy rake db:migrate:reset
.
Nếu vấn đề trên xảy ra, và tại một thời điểm khác ai đó chạy rake db:migrate
, sẽ thu được một file schema.rb
không chuẩn, và sau đó sẽ rất khó để giải quyết những vấn đề phát sinh tiếp theo.
Giải quyết như thế nào mới đúng?
Có một cách tiếp cận mạnh mẽ để giải quyết vấn đề trên đó là xây dựng lại schema.rb
ở từng giai đoạn như sau:
- Trước khi rebase, checkout và pull nhánh develop và phải đảm bảo rằng database đang tương đồng với version schema hiện tại ở nhánh develop. Bạn có thể kiểm tra việc này bằng cách chạy
rake db:migrate:status
. Trường hợp lý tưởng là mọi thứ bạn nhìn thấy đều làup
.- Nếu có một vài file là
down
, thì rất có thể bạn chưa migrate tất cả các file migration có ở trên develop, do vậy hãy chạy lệnhrake db:migrate
- Nếu bạn thấy có dòng nào đó như sau, có nghĩa là một migration nào đó đã được applied vào database mà lại chưa có trên develop, và có thể đó là migration ở nhánh của bạn đang thực hiện một tính năng và cần rebase.
Rails
không có cơ chế rollback migration này, vì vậy bạn cần chuyển sang một nhánh bất kỳ nào khác và tự thêm một file migration để rollback lại.up 20170210155150 ********** NO FILE ***********
- Nếu có một vài file là
- Bậy giờ bạn có thể chuyển sang nhánh của mình và rebase với develop
- Khi xảy ra conflict, đầu tiên hãy unstage những thay đổi của file
schema.rb
git reset HEAD db/schema.rb
- Tiếp theo discard những thay đổi của file
schema.rb
ở trên nhánh của mìnhgit checkout db/schema.rb
- Build lại schema
rake db:migrate
- Kiểm tra sự khác biệt
git diff
của file schema.rb- Trong trường hợp những file migration bạn thêm vào sớm hơn trên develop, version của file schema.rb sẽ không thay đổi vì nó tương ứng với file migration mới nhất (có timestamp lớn nhất).
- Đó là những gì bạn cần làm nếu gặp vấn đề khi rebase file
schema.rb
. Bây giờ hãy tiếp tục rebase những file conflict khác.
Background
Những điều bạn cần biết để hiểu rõ ràng hơn những thứ ở trên hoạt động:
schema.rb
là file được xây dựng từ cơ sở dữ liệu, không phải trực tiếp từ migrations.- Khi
rake db:migrate
được chạy, nó sẽ check bảngschema_migrations
trong database (bảng này chứa danh sách timestamp của các migrations đã được chạy trên cơ sở dữ liệu) và so sánh vớidb/migrations
, sau đó nó sẽ chạy những migration nào chưa được chạy và thêm dấu thời gian vào bảngschema_migrations
, và rebuild lại schema. rake db:migrate:status
chỉ show ra sự khác nhau giữa bảngschema_migrations
vàdb/migrations
chứ không thay đổi gì cả.- Các schema nói chung đa phần đều xây dựng theo cùng một cách ngay cả khi một số file migration không đúng theo trật tự, bởi vì các chỉ mục mới được thêm vào theo thứ tự chữ cái chứ không phải theo thứ tự của migration.
Kết luận
Mong rằng bài viết sẽ hữu ích với các bạn. Cảm ơn. References
All rights reserved