1. Hướng dẫn chi tiết về Git cho người mới bắt đầu

Hôm nay chúng ta sẽ nói về một hệ thống kiểm soát phiên bản, cụ thể là Git.

Bạn thực sự không thể trở thành một lập trình viên chính thức nếu không biết và hiểu công cụ này. Tất nhiên, bạn không cần phải nhớ tất cả các lệnh và tính năng của Git trong đầu để có thể tiếp tục làm việc. Bạn cần biết một tập hợp các lệnh sẽ giúp bạn hiểu mọi thứ đang diễn ra.

Khái niệm cơ bản về Git

Git là một hệ thống kiểm soát phiên bản phân tán cho mã của chúng tôi. Tại sao chúng ta cần nó? Các nhóm cần một số loại hệ thống để quản lý công việc của họ. Nó là cần thiết để theo dõi những thay đổi xảy ra theo thời gian.

Nghĩa là, chúng ta cần có thể xem từng bước những tệp nào đã thay đổi và thay đổi như thế nào. Điều này đặc biệt quan trọng khi bạn đang điều tra những gì đã thay đổi trong ngữ cảnh của một tác vụ đơn lẻ, giúp bạn có thể hoàn nguyên các thay đổi.

Hãy tưởng tượng tình huống sau: chúng tôi có mã đang hoạt động, mọi thứ trong đó đều tốt, nhưng sau đó chúng tôi quyết định cải thiện hoặc chỉnh sửa một số thứ. Không có gì to tát, nhưng "cải tiến" của chúng tôi đã phá vỡ một nửa tính năng của chương trình và khiến nó không thể hoạt động. Thế bây giờ thì thế nào? Nếu không có Git, bạn sẽ phải ngồi suy nghĩ hàng giờ đồng hồ, cố nhớ xem mọi thứ ban đầu như thế nào. Nhưng với Git, chúng tôi chỉ cần khôi phục cam kết — và thế là xong.

Hoặc nếu có hai nhà phát triển thực hiện thay đổi mã của riêng họ cùng một lúc thì sao? Không có Git, họ sao chép các tệp mã gốc và sửa đổi chúng một cách riêng biệt. Sẽ có lúc cả hai muốn thêm các thay đổi của họ vào thư mục chính. Bạn làm gì trong trường hợp này?

Sẽ không có vấn đề như vậy nếu bạn sử dụng Git.

Cài đặt Git

Hãy cài đặt Java trên máy tính của bạn Quá trình này hơi khác đối với các hệ điều hành khác nhau.

Cài đặt trên Windows

Như thường lệ, bạn cần tải xuống và chạy một tệp exe. Mọi thứ ở đây đều đơn giản: nhấp vào liên kết Google đầu tiên , thực hiện cài đặt, thế là xong. Để làm điều này, chúng tôi sẽ sử dụng bảng điều khiển bash do Windows cung cấp.

Trên Windows, bạn cần chạy Git Bash. Đây là giao diện của nó trong Menu Bắt đầu:

Bây giờ, đây là dấu nhắc lệnh mà bạn có thể làm việc.

Để tránh phải vào thư mục với dự án mỗi lần để mở Git ở đó, bạn có thể mở dấu nhắc lệnh trong thư mục dự án bằng nút chuột phải với đường dẫn chúng tôi cần:

Cài đặt trên Linux

Thông thường Git là một phần của các bản phân phối Linux và đã được cài đặt sẵn, vì nó là một công cụ ban đầu được viết để phát triển nhân Linux. Nhưng có những tình huống khi nó không phải là. Để kiểm tra, bạn cần mở terminal và viết: git --version. Nếu bạn nhận được câu trả lời dễ hiểu, thì không cần cài đặt gì nữa.

Mở một thiết bị đầu cuối và cài đặt. Đối với Ubuntu, bạn cần viết: sudo apt-get install git. Và thế là xong: bây giờ bạn có thể sử dụng Git trong bất kỳ thiết bị đầu cuối nào.

Cài đặt trên macOS

Ở đây cũng vậy, trước tiên bạn cần kiểm tra xem Git đã có chưa (xem ở trên, giống như trên Linux).

Nếu bạn không có nó, thì cách dễ nhất để lấy nó là tải xuống phiên bản mới nhất . Nếu Xcode được cài đặt, thì Git chắc chắn sẽ được cài đặt tự động.

Cài đặt Git

Git có cài đặt người dùng cho người dùng sẽ gửi công việc. Điều này hợp lý và cần thiết, vì Git lấy thông tin này cho trường Tác giả khi một cam kết được tạo.

Thiết lập tên người dùng và mật khẩu cho tất cả các dự án của bạn bằng cách chạy các lệnh sau:

git config --global user.name "Ivan Ivanov" git config --global user.email ivan.ivanov@gmail.com

Nếu bạn cần thay đổi tác giả cho một dự án cụ thể (ví dụ: dự án cá nhân), bạn có thể xóa "--global". Điều này sẽ cung cấp cho chúng tôi những điều sau đây:

git config user.name "Ivan Ivanov" git config user.email ivan.ivanov@gmail.com

Một chút lý thuyết

Để đi sâu vào chủ đề, chúng tôi nên giới thiệu với bạn một số từ và hành động mới... Nếu không, sẽ không có gì để nói. Tất nhiên, đây là biệt ngữ đến với chúng tôi từ tiếng Anh, vì vậy tôi sẽ thêm các bản dịch trong ngoặc đơn.

lời nói và hành động gì?

  • kho git
  • làm
  • chi nhánh
  • hợp nhất
  • xung đột
  • sự lôi kéo
  • cách bỏ qua một số tệp (.gitignore)

Và như thế.

Trạng thái trong Git

Git có một số bức tượng cần được hiểu và ghi nhớ:

  • không bị theo dõi
  • sửa đổi
  • dàn dựng
  • tận tụy

Bạn nên hiểu điều này như thế nào?

Đây là những trạng thái áp dụng cho các tệp chứa mã của chúng tôi. Nói cách khác, vòng đời của chúng thường như sau:

  • Một tệp được tạo nhưng chưa được thêm vào kho lưu trữ có trạng thái "không bị theo dõi".
  • Khi chúng tôi thay đổi các tệp đã được thêm vào kho lưu trữ Git, thì trạng thái của chúng là "đã sửa đổi".
  • Trong số các tệp mà chúng tôi đã thay đổi, chúng tôi chọn những tệp chúng tôi cần (ví dụ: chúng tôi không cần các lớp đã biên dịch) và các lớp này được thay đổi thành trạng thái "dàn dựng".
  • Một cam kết được tạo từ các tệp đã chuẩn bị ở trạng thái theo giai đoạn và đi vào kho lưu trữ Git. Sau đó, không có tệp nào có trạng thái "dàn dựng". Nhưng vẫn có thể có các tệp có trạng thái "đã sửa đổi".

Cái này nó thì trông như thế nào:

Cam kết là gì?

Cam kết là sự kiện chính khi nói đến kiểm soát phiên bản. Nó chứa tất cả các thay đổi được thực hiện kể từ khi bắt đầu cam kết. Các cam kết được liên kết với nhau giống như một danh sách được liên kết đơn lẻ.

Cụ thể, có một cam kết đầu tiên. Khi lần xác nhận thứ hai được tạo, nó (lần thứ hai) biết điều gì xảy ra sau lần đầu tiên. Và theo cách này, thông tin có thể được theo dõi.

Một cam kết cũng có thông tin riêng của nó, được gọi là siêu dữ liệu:

  • mã định danh duy nhất của cam kết, có thể được sử dụng để tìm thấy nó
  • tên của tác giả của cam kết, người đã tạo ra nó
  • ngày cam kết được tạo
  • một bình luận mô tả những gì đã được thực hiện trong quá trình cam kết

Đây là giao diện của nó:

Chi nhánh là gì?

Một nhánh là một con trỏ tới một số cam kết. Bởi vì một lần xác nhận biết lần xác nhận nào trước nó, khi một nhánh trỏ đến một lần xác nhận, tất cả các lần xác nhận trước đó cũng áp dụng cho nó.

Theo đó, chúng tôi có thể nói rằng bạn có thể có bao nhiêu nhánh tùy ý trỏ đến cùng một cam kết.

Công việc xảy ra trong các nhánh, vì vậy khi một lần xác nhận mới được tạo, nhánh sẽ di chuyển con trỏ của nó tới lần xác nhận gần đây hơn.

Bắt đầu với Git

Bạn có thể làm việc với kho lưu trữ cục bộ một mình cũng như với kho lưu trữ từ xa.

Để thực hành các lệnh cần thiết, bạn có thể giới hạn bản thân trong kho lưu trữ cục bộ. Nó chỉ lưu trữ cục bộ tất cả thông tin của dự án trong thư mục .git.

Nếu chúng ta đang nói về kho lưu trữ từ xa, thì tất cả thông tin được lưu trữ ở đâu đó trên máy chủ từ xa: chỉ một bản sao của dự án được lưu trữ cục bộ. Những thay đổi được thực hiện đối với bản sao cục bộ của bạn có thể được đẩy (git push) vào kho lưu trữ từ xa.

Trong cuộc thảo luận của chúng tôi ở đây và bên dưới, chúng tôi đang nói về việc làm việc với Git trong bảng điều khiển. Tất nhiên, bạn có thể sử dụng một số loại giải pháp dựa trên GUI (ví dụ: IntelliJ IDEA), nhưng trước tiên, bạn nên tìm hiểu những lệnh nào đang được thực thi và ý nghĩa của chúng.

Làm việc với Git trong kho lưu trữ cục bộ

Để tạo một kho lưu trữ cục bộ, bạn cần viết:

git init

Điều này sẽ tạo một thư mục .git ẩn trong thư mục hiện tại của bảng điều khiển.

Thư mục .git lưu trữ tất cả thông tin về kho lưu trữ Git. Đừng xóa nó ;)

Tiếp theo, các tệp được thêm vào dự án và chúng được gán trạng thái "Không bị theo dõi". Để kiểm tra tình trạng hiện tại của công việc của bạn, viết này:

trạng thái git

Chúng tôi đang ở trong nhánh chính và chúng tôi sẽ ở đây cho đến khi chuyển sang nhánh khác.

Điều này cho biết những tệp nào đã thay đổi nhưng chưa được thêm vào trạng thái "dàn dựng". Để thêm chúng vào trạng thái "dàn dựng", bạn cần viết "git add". Chúng tôi có một vài lựa chọn ở đây, ví dụ:

  • git add -A — thêm tất cả các tệp vào trạng thái "dàn dựng"
  • git thêm . — thêm tất cả các tệp từ thư mục này và tất cả các thư mục con. Về cơ bản giống như cái trước;
  • git add <file name> — thêm một tệp cụ thể. Tại đây, bạn có thể sử dụng các biểu thức chính quy để thêm tệp theo một số mẫu. Ví dụ: git add *.java: Điều này có nghĩa là bạn chỉ muốn thêm các tệp có phần mở rộng java.

Hai tùy chọn đầu tiên rõ ràng là đơn giản. Mọi thứ trở nên thú vị hơn với phần bổ sung mới nhất, vì vậy hãy viết:

git add *.txt

Để kiểm tra trạng thái, chúng tôi sử dụng lệnh đã biết:

trạng thái git

Tại đây, bạn có thể thấy rằng biểu thức chính quy đã hoạt động chính xác: test_resource.txt hiện có trạng thái "dàn dựng".

Và cuối cùng, giai đoạn cuối cùng để làm việc với kho lưu trữ cục bộ (còn một bước nữa khi làm việc với kho lưu trữ từ xa ;)) — tạo một cam kết mới:

git commit -m “tất cả các tệp txt đã được thêm vào dự án”

Tiếp theo là một lệnh tuyệt vời để xem lịch sử cam kết trên một nhánh. Hãy tận dụng nó:

nhật ký git

Ở đây bạn có thể thấy rằng chúng tôi đã tạo cam kết đầu tiên của mình và nó bao gồm văn bản mà chúng tôi đã cung cấp trên dòng lệnh. Điều rất quan trọng là phải hiểu rằng văn bản này phải giải thích chính xác nhất có thể những gì đã được thực hiện trong quá trình cam kết này. Điều này sẽ giúp chúng tôi nhiều lần trong tương lai.

Một độc giả tò mò chưa ngủ có thể thắc mắc điều gì đã xảy ra với tệp GitTest.java. Hãy cùng tìm hiểu ngay bây giờ. Để làm điều này, chúng tôi sử dụng:

trạng thái git

Như bạn có thể thấy, nó vẫn "không bị theo dõi" và đang chờ đợi trong đôi cánh. Nhưng nếu chúng ta không muốn thêm nó vào dự án thì sao? Đôi khi điều đó xảy ra.

Để làm cho mọi thứ thú vị hơn, bây giờ chúng ta hãy thử thay đổi tệp test_resource.txt của mình. Hãy thêm một số văn bản ở đó và kiểm tra trạng thái:

trạng thái git

Tại đây, bạn có thể thấy rõ sự khác biệt giữa trạng thái "không bị theo dõi" và "đã sửa đổi".

GitTest.java là "không bị theo dõi", trong khi test_resource.txt là "đã sửa đổi".

Bây giờ chúng tôi có các tệp ở trạng thái đã sửa đổi, chúng tôi có thể kiểm tra các thay đổi được thực hiện đối với chúng. Điều này có thể được thực hiện bằng cách sử dụng lệnh sau:

git diff

Đó là, bạn có thể thấy rõ ở đây những gì tôi đã thêm vào tệp văn bản của chúng tôi: xin chào thế giới!

Hãy thêm các thay đổi của chúng tôi vào tệp văn bản và tạo một cam kết:

git thêm test_resource.txt
git commit -m “đã thêm từ xin chào! đến test_resource.txt”

Để xem xét tất cả các cam kết, hãy viết:

nhật ký git

Như bạn có thể thấy, bây giờ chúng ta có hai lần xác nhận.

Chúng ta sẽ thêm GitTest.java theo cách tương tự. Không có bình luận ở đây, chỉ có lệnh:

git thêm GitTest.java
git commit -m “đã thêm GitTest.java”
trạng thái git

Làm việc với .gitignore

Rõ ràng, chúng tôi chỉ muốn giữ riêng mã nguồn và không có gì khác trong kho lưu trữ. Vì vậy, những gì khác có thể có? Ở mức tối thiểu, các lớp và/hoặc tệp được biên dịch do môi trường phát triển tạo ra.

Để yêu cầu Git bỏ qua chúng, chúng ta cần tạo một tệp đặc biệt. Thực hiện việc này: tạo một tệp có tên .gitignore trong thư mục gốc của dự án. Mỗi dòng trong tệp này đại diện cho một mẫu để bỏ qua.

Trong ví dụ này, tệp .gitignore sẽ trông như thế này:

*.mục
tiêu lớp/
*.iml
.idea/

Hãy cùng xem:

  • Dòng đầu tiên là bỏ qua tất cả các tệp có phần mở rộng .class
  • Dòng thứ hai là bỏ qua thư mục "đích" và mọi thứ chứa trong đó
  • Dòng thứ ba là bỏ qua tất cả các tệp có phần mở rộng .iml
  • Dòng thứ tư là bỏ qua thư mục .idea

Hãy thử sử dụng một ví dụ. Để xem nó hoạt động như thế nào, hãy thêm GitTest.class đã biên dịch vào dự án và kiểm tra trạng thái dự án:

trạng thái git

Rõ ràng, chúng tôi không muốn vô tình thêm lớp đã biên dịch vào dự án (sử dụng git add -A). Để thực hiện việc này, hãy tạo tệp .gitignore và thêm mọi thứ đã được mô tả trước đó:

Bây giờ, hãy sử dụng một cam kết để thêm tệp .gitignore vào dự án:

git thêm .gitignore
git commit -m “đã thêm tệp .gitignore”

Và bây giờ là thời điểm của sự thật: chúng tôi có một lớp GitTest.class đã biên dịch là "không bị theo dõi", mà chúng tôi không muốn thêm vào kho lưu trữ Git.

Bây giờ chúng ta sẽ thấy tác dụng của tệp .gitignore:

trạng thái git

Hoàn hảo! .gitignore +1 :)

Làm việc với các chi nhánh

Đương nhiên, làm việc chỉ trong một chi nhánh sẽ gây bất tiện cho các nhà phát triển đơn độc và điều đó là không thể khi có nhiều hơn một người trong nhóm. Đây là lý do tại sao chúng tôi có các chi nhánh.

Một nhánh chỉ là một con trỏ di động để xác nhận.

Trong phần này, chúng ta sẽ khám phá cách làm việc trong các nhánh khác nhau: cách hợp nhất các thay đổi từ nhánh này sang nhánh khác, xung đột nào có thể phát sinh, v.v.

Để xem danh sách tất cả các nhánh trong kho lưu trữ và hiểu bạn đang ở nhánh nào, bạn cần viết:

nhánh git -a

Bạn có thể thấy rằng chúng tôi chỉ có một nhánh chính. Dấu hoa thị phía trước cho biết chúng tôi đang ở trong đó. Nhân tiện, bạn cũng có thể sử dụng lệnh "git status" để biết chúng ta đang ở nhánh nào.

Sau đó, có một số tùy chọn để tạo các nhánh (có thể có nhiều hơn - đây là những tùy chọn mà tôi sử dụng):

  • tạo một nhánh mới dựa trên nhánh chúng tôi đang ở (99% trường hợp)
  • tạo một nhánh dựa trên một cam kết cụ thể (1% trường hợp)

Hãy tạo một nhánh dựa trên một cam kết cụ thể

Chúng tôi sẽ dựa vào số nhận dạng duy nhất của cam kết. Để tìm thấy nó, chúng tôi viết:

nhật ký git

Chúng tôi đã đánh dấu cam kết bằng nhận xét "đã thêm xin chào thế giới..." Số nhận dạng duy nhất của nó là 6c44e53d06228f888f2f454d3cb8c1c976dd73f8. Chúng tôi muốn tạo một nhánh "phát triển" bắt đầu từ cam kết này. Để làm điều này, chúng tôi viết:

kiểm tra git -b phát triển 6c44e53d06228f888f2f454d3cb8c1c976dd73f8

Một nhánh được tạo chỉ với hai lần xác nhận đầu tiên từ nhánh chính. Để xác minh điều này, trước tiên chúng tôi đảm bảo chuyển sang một nhánh khác và xem số lần xác nhận ở đó:

trạng thái git
nhật ký git

Và như mong đợi, chúng tôi có hai lần xác nhận. Nhân tiện, đây là một điểm thú vị: chưa có tệp .gitignore trong nhánh này, vì vậy tệp đã biên dịch của chúng tôi (GitTest.class) hiện được đánh dấu bằng trạng thái "không bị theo dõi".

Bây giờ chúng ta có thể xem xét lại các chi nhánh của mình bằng cách viết điều này:

nhánh git -a

Bạn có thể thấy rằng có hai nhánh: "chính chủ" và "phát triển". Chúng tôi hiện đang trong quá trình phát triển.

Hãy tạo một nhánh dựa trên nhánh hiện tại

Cách thứ hai để tạo một nhánh là tạo nó từ một nhánh khác. Chúng tôi muốn tạo một nhánh dựa trên nhánh chính. Đầu tiên, chúng ta cần chuyển sang nó và bước tiếp theo là tạo một cái mới. Hãy cùng xem:

  • git checkout master — chuyển sang nhánh chính
  • trạng thái git - xác minh rằng chúng tôi thực sự đang ở nhánh chính

Ở đây bạn có thể thấy rằng chúng tôi đã chuyển sang nhánh chính, tệp .gitignore có hiệu lực và lớp đã biên dịch không còn được đánh dấu là "không bị theo dõi".

Bây giờ chúng ta tạo một nhánh mới dựa trên nhánh chính:

git checkout -b feature/update-txt-files

Nếu bạn không chắc liệu nhánh này có giống với nhánh "chính" hay không, bạn có thể dễ dàng kiểm tra bằng cách thực hiện "git log" và xem xét tất cả các lần xác nhận. Nên có bốn người trong số họ.

giải quyết xung đột

Trước khi khám phá xung đột là gì, chúng ta cần nói về việc hợp nhất một nhánh với một nhánh khác.

Hình ảnh này mô tả quá trình hợp nhất một chi nhánh với một chi nhánh khác:

Ở đây, chúng tôi có một chi nhánh chính. Tại một số điểm, một nhánh phụ được tạo ra từ nhánh chính và sau đó được sửa đổi. Sau khi hoàn thành công việc, chúng ta cần hợp nhất nhánh này với nhánh kia.

Trong ví dụ của chúng tôi, chúng tôi đã tạo nhánh feature/update-txt-files. Như được chỉ định bởi tên của chi nhánh, chúng tôi đang cập nhật văn bản.

Bây giờ chúng ta cần tạo một commit mới cho công việc này:

git add *.txt
git commit -m “tệp txt đã cập nhật”
nhật ký git

Bây giờ, nếu chúng ta muốn hợp nhất nhánh feature/update-txt-files thành master, chúng ta cần vào master và viết "git merge feature/update-txt-files":

chủ kiểm tra git
tính năng hợp nhất git/tệp cập nhật-txt
nhật ký git

Do đó, nhánh chính hiện cũng bao gồm cam kết đã được thêm vào tệp tính năng/cập nhật-txt-.

Chức năng này đã được thêm vào, vì vậy bạn có thể xóa một nhánh tính năng. Để làm điều này, chúng tôi viết:

nhánh git -D tính năng/cập nhật-tệp txt

Hãy làm phức tạp tình hình: bây giờ giả sử rằng bạn cần thay đổi lại tệp txt. Nhưng bây giờ tệp này cũng sẽ được thay đổi trong nhánh chính. Nói cách khác, nó sẽ thay đổi song song. Git sẽ không thể biết phải làm gì khi chúng ta muốn hợp nhất mã mới của mình vào nhánh chính.

Chúng tôi sẽ tạo một nhánh mới dựa trên master, thực hiện các thay đổi đối với text_resource.txt và tạo một cam kết cho công việc này:

git checkout -b feature/add-header

... chúng tôi thực hiện các thay đổi đối với tệp

git add *.txt
git commit -m “đã thêm tiêu đề vào txt”

Chuyển đến nhánh chính và cũng cập nhật tệp văn bản này trên cùng một dòng như trong nhánh tính năng:

chủ kiểm tra git

… chúng tôi đã cập nhật test_resource.txt

git thêm test_resource.txt
git commit -m “đã thêm tiêu đề chính vào txt”

Và bây giờ là điểm thú vị nhất: chúng ta cần hợp nhất các thay đổi từ nhánh feature/add-header thành master. Chúng tôi đang ở trong nhánh chính, vì vậy chúng tôi chỉ cần viết:

tính năng hợp nhất git/tiêu đề bổ sung

Nhưng kết quả sẽ là xung đột trong file test_resource.txt:

Ở đây chúng ta có thể thấy rằng Git không thể tự quyết định cách hợp nhất mã này. Nó cho chúng tôi biết rằng chúng tôi cần giải quyết xung đột trước và chỉ sau đó mới thực hiện cam kết.

ĐƯỢC RỒI. Chúng tôi mở tệp có xung đột trong trình soạn thảo văn bản và xem:

Để hiểu những gì Git đã làm ở đây, chúng ta cần nhớ chúng ta đã thực hiện những thay đổi nào và ở đâu, sau đó so sánh:

  1. Những thay đổi trên dòng này trong nhánh chính được tìm thấy giữa "<<<<<<< HEAD" và "=======".
  2. Các thay đổi trong nhánh tính năng/tiêu đề bổ sung được tìm thấy giữa "=======" và ">>>>>>> tính năng/tiêu đề bổ sung".

Đây là cách Git cho chúng ta biết rằng nó không thể tìm ra cách thực hiện hợp nhất tại vị trí này trong tệp. Nó chia phần này thành hai phần từ các nhánh khác nhau và mời chúng tôi tự giải quyết xung đột hợp nhất.

Đủ công bằng. Tôi mạnh dạn quyết định loại bỏ tất cả, chỉ để lại từ "tiêu đề":

Hãy nhìn vào trạng thái của những thay đổi. Mô tả sẽ hơi khác một chút. Thay vì trạng thái "đã sửa đổi", chúng tôi đã "không hợp nhất". Vì vậy, chúng ta có thể đã đề cập đến một trạng thái thứ năm? Tôi không nghĩ rằng điều này là cần thiết. Hãy xem nào:

trạng thái git

Chúng ta có thể thuyết phục bản thân rằng đây là một trường hợp đặc biệt, bất thường. Tiếp tục đi:

git add *.txt

Bạn có thể nhận thấy rằng phần mô tả chỉ đề xuất viết "git commit". Hãy thử viết rằng:

cam kết git

Và cứ như vậy, chúng tôi đã làm được — chúng tôi đã giải quyết xung đột trong bảng điều khiển.

Tất nhiên, điều này có thể được thực hiện dễ dàng hơn một chút trong môi trường phát triển tích hợp. Ví dụ: trong IntelliJ IDEA, mọi thứ được thiết lập tốt đến mức bạn có thể thực hiện tất cả các hành động cần thiết ngay trong đó. Nhưng các IDE làm rất nhiều thứ "dưới mui xe" và chúng ta thường không hiểu chính xác điều gì đang xảy ra ở đó. Và khi không có sự hiểu biết, vấn đề có thể nảy sinh.

Làm việc với các kho lưu trữ từ xa

Bước cuối cùng là tìm ra thêm một số lệnh cần thiết để làm việc với kho lưu trữ từ xa.

Như tôi đã nói, kho lưu trữ từ xa là một nơi mà kho lưu trữ được lưu trữ và từ đó bạn có thể sao chép nó.

Có những loại kho lưu trữ từ xa nào? Ví dụ:

  • GitHub là nền tảng lưu trữ lớn nhất cho các kho lưu trữ và phát triển hợp tác.
  • GitLab là một công cụ dựa trên web dành cho vòng đời DevOps với mã nguồn mở. Nó là một hệ thống dựa trên Git để quản lý kho lưu trữ mã với wiki riêng, hệ thống theo dõi lỗi, đường dẫn CI/CD và các chức năng khác.
  • BitBucket là một dịch vụ web để lưu trữ dự án và phát triển cộng tác dựa trên hệ thống kiểm soát phiên bản Mercurial và Git. Đã có lúc nó có lợi thế lớn so với GitHub ở chỗ nó cung cấp các kho lưu trữ riêng miễn phí. Năm ngoái, GitHub cũng đã giới thiệu miễn phí khả năng này cho mọi người.
  • Và như thế…

Khi làm việc với kho lưu trữ từ xa, điều đầu tiên cần làm là sao chép dự án vào kho lưu trữ cục bộ của bạn.

Đối với điều này, chúng tôi đã xuất dự án mà chúng tôi đã thực hiện tại địa phương Bây giờ mọi người có thể sao chép dự án đó cho chính mình bằng cách viết:

bản sao git https://github.com/romankh3/git-demo

Hiện tại đã có một bản sao cục bộ hoàn chỉnh của dự án. Để đảm bảo rằng bản sao cục bộ của dự án là mới nhất, bạn cần kéo dự án bằng cách viết:

kéo git

Trong trường hợp của chúng tôi, hiện tại không có gì trong kho lưu trữ từ xa thay đổi, vì vậy phản hồi là: Đã cập nhật.

Nhưng nếu chúng tôi thực hiện bất kỳ thay đổi nào đối với kho lưu trữ từ xa, kho lưu trữ cục bộ sẽ được cập nhật sau khi chúng tôi kéo chúng.

Và cuối cùng, lệnh cuối cùng là đẩy dữ liệu đến kho lưu trữ từ xa. Khi chúng tôi đã thực hiện một cái gì đó cục bộ và muốn gửi nó đến kho lưu trữ từ xa, trước tiên chúng tôi phải tạo một cam kết mới cục bộ. Để chứng minh điều này, hãy thêm một cái gì đó khác vào tệp văn bản của chúng tôi:

Bây giờ, một điều khá phổ biến đối với chúng tôi - chúng tôi tạo một cam kết cho công việc này:

git thêm test_resource.txt
git commit -m "đã chuẩn bị txt để đẩy"

Lệnh để đẩy cái này vào kho lưu trữ từ xa là:

đẩy git

Đó là nó cho bây giờ!

Liên kết hữu ích

2. Cách làm việc với Git trong IntelliJ IDEA

Trong phần này, bạn sẽ học cách làm việc với Git trong IntelliJ IDEA.

Yêu cầu đầu vào:

  1. Đọc, theo dõi và hiểu phần trước. Điều này sẽ giúp đảm bảo rằng mọi thứ đã được thiết lập và sẵn sàng hoạt động.
  2. Cài đặt IntelliJ IDEA. Mọi thứ nên theo thứ tự ở đây :)
  3. Phân bổ một giờ để đạt được sự thành thạo hoàn toàn.

Hãy làm việc với dự án demo mà tôi đã sử dụng cho bài viết về Git.

Sao chép dự án cục bộ

Có hai lựa chọn ở đây:

  1. Nếu bạn đã có tài khoản GitHub và muốn đẩy thứ gì đó sau này, tốt hơn là rẽ nhánh dự án và sao chép bản sao của riêng bạn. Bạn có thể đọc về cách tạo một nhánh trong một bài viết khác dưới tiêu đề Một ví dụ về quy trình tạo nhánh .
  2. Sao chép kho lưu trữ và thực hiện mọi thứ cục bộ mà không có khả năng đẩy toàn bộ nội dung lên máy chủ.

Để sao chép một dự án từ GitHub, bạn cần sao chép liên kết dự án và chuyển nó tới IntelliJ IDEA:

  1. Sao chép địa chỉ dự án:

  2. Mở IntelliJ IDEA và chọn "Nhận từ Kiểm soát phiên bản":

  3. Sao chép và dán địa chỉ dự án:

  4. Bạn sẽ được nhắc tạo một dự án IntelliJ IDEA. Chấp nhận đề nghị:

  5. Vì không có hệ thống xây dựng, chúng tôi chọn "Tạo dự án từ các nguồn hiện có":

  6. Tiếp theo, bạn sẽ thấy màn hình tuyệt đẹp này:

Bây giờ chúng tôi đã tìm ra cách nhân bản, bạn có thể xem xung quanh.

Cái nhìn đầu tiên về IntelliJ IDEA dưới dạng giao diện người dùng Git

Hãy xem kỹ dự án nhân bản: bạn đã có thể nhận được rất nhiều thông tin về hệ thống kiểm soát phiên bản.

Đầu tiên, chúng ta có ngăn Kiểm soát phiên bản ở góc dưới bên trái. Tại đây, bạn có thể tìm thấy tất cả các thay đổi cục bộ và nhận danh sách các lần xác nhận (tương tự như "git log").

Hãy chuyển sang thảo luận về Nhật ký. Có một hình dung nhất định giúp chúng ta hiểu chính xác quá trình phát triển đã diễn ra như thế nào. Ví dụ: bạn có thể thấy rằng một nhánh mới đã được tạo với tiêu đề được thêm vào txt cam kết, sau đó được hợp nhất vào nhánh chính. Nếu bạn nhấp vào một cam kết, bạn có thể thấy ở góc bên phải tất cả thông tin về cam kết: tất cả các thay đổi và siêu dữ liệu của nó.

Hơn nữa, bạn có thể thấy những thay đổi thực tế. Chúng tôi cũng thấy rằng một cuộc xung đột đã được giải quyết ở đó. IDEA cũng trình bày điều này rất tốt.

Nếu bạn nhấp đúp vào tệp đã được thay đổi trong quá trình xác nhận này, chúng tôi sẽ xem xung đột đã được giải quyết như thế nào:

Chúng tôi lưu ý rằng ở bên trái và bên phải, chúng tôi có hai phiên bản của cùng một tệp cần được hợp nhất thành một. Và ở giữa, chúng ta có kết quả hợp nhất cuối cùng.

Khi một dự án có nhiều nhánh, cam kết và người dùng, bạn cần tìm kiếm riêng theo nhánh, người dùng và ngày:

Trước khi bắt đầu, cũng đáng để giải thích cách hiểu chúng ta đang ở nhánh nào.

Ở góc dưới bên phải, có một nút có nhãn "Git: master". Bất cứ thứ gì theo sau "Git:" là nhánh hiện tại. Nếu bạn nhấp vào nút, bạn có thể thực hiện rất nhiều điều hữu ích: chuyển sang nhánh khác, tạo nhánh mới, đổi tên nhánh hiện có, v.v.

Làm việc với một kho lưu trữ

phím nóng hữu ích

Đối với công việc trong tương lai, bạn cần nhớ một vài phím nóng rất hữu ích:

  1. CTRL+T — Nhận các thay đổi mới nhất từ ​​kho lưu trữ từ xa (git pull).
  2. CTRL+K — Tạo một cam kết / xem tất cả các thay đổi hiện tại. Điều này bao gồm cả tệp không bị theo dõi và tệp đã sửa đổi (git commit).
  3. CTRL+SHIFT+K — Đây là lệnh đẩy các thay đổi vào kho lưu trữ từ xa. Tất cả các xác nhận được tạo cục bộ và chưa có trong kho lưu trữ từ xa sẽ được đẩy (git đẩy).
  4. ALT+CTRL+Z — Khôi phục các thay đổi trong một tệp cụ thể về trạng thái của lần xác nhận cuối cùng được tạo trong kho lưu trữ cục bộ. Nếu bạn chọn toàn bộ dự án ở góc trên bên trái, bạn có thể khôi phục các thay đổi trong tất cả các tệp.

Chúng ta muốn gì?

Để hoàn thành công việc, chúng ta cần nắm vững một kịch bản cơ bản được sử dụng ở mọi nơi.

Mục tiêu là triển khai chức năng mới trong một nhánh riêng biệt và sau đó đẩy nó tới một kho lưu trữ từ xa (sau đó bạn cũng cần tạo một yêu cầu kéo tới nhánh chính, nhưng điều đó nằm ngoài phạm vi của bài học này).

Điều gì là cần thiết để làm điều này?

  1. Nhận tất cả các thay đổi hiện tại trong nhánh chính (ví dụ: "chính").

  2. Từ nhánh chính này, tạo một nhánh riêng cho công việc của bạn.

  3. Triển khai chức năng mới.

  4. Đi đến nhánh chính và kiểm tra xem có bất kỳ thay đổi mới nào trong khi chúng tôi đang làm việc không. Nếu không, thì mọi thứ đều ổn. Nhưng nếu có thay đổi, thì chúng tôi làm như sau: đi đến nhánh đang hoạt động và khởi động lại các thay đổi từ nhánh chính sang nhánh của chúng tôi. Nếu mọi thứ suôn sẻ, thì thật tuyệt. Nhưng hoàn toàn có thể xảy ra xung đột. Khi nó xảy ra, chúng chỉ có thể được giải quyết trước mà không lãng phí thời gian trong kho lưu trữ từ xa.

    Bạn có tự hỏi tại sao bạn nên làm điều này? Đó là cách cư xử tốt và ngăn xung đột xảy ra sau khi đẩy nhánh của bạn đến kho lưu trữ cục bộ (tất nhiên, có khả năng xung đột vẫn xảy ra, nhưng nó sẽ nhỏ hơn nhiều ).

  5. Đẩy các thay đổi của bạn vào kho lưu trữ từ xa.

Làm cách nào để nhận các thay đổi từ máy chủ từ xa?

Chúng tôi đã thêm một mô tả vào README với một cam kết mới và muốn nhận những thay đổi này. Nếu các thay đổi được thực hiện cả trong kho lưu trữ cục bộ và kho lưu trữ từ xa, thì chúng tôi được mời chọn giữa hợp nhất và khởi động lại. Chúng tôi chọn hợp nhất.

Nhập CTRL+T :

Bây giờ bạn có thể thấy README đã thay đổi như thế nào, tức là những thay đổi từ kho lưu trữ từ xa đã được kéo vào và ở góc dưới bên phải, bạn có thể xem tất cả chi tiết về những thay đổi đến từ máy chủ.

Tạo một nhánh mới dựa trên master

Mọi thứ đều đơn giản ở đây.

Đi đến góc dưới cùng bên phải và nhấp vào Git: master . Chọn + Chi nhánh mới .

Bỏ chọn hộp kiểm Chi nhánh thanh toán và nhập tên của chi nhánh mới. Trong trường hợp của chúng tôi: đây sẽ là readme-improver .

Git: master sau đó sẽ đổi thành Git: readme-improver .

Hãy mô phỏng công việc song song

Để xung đột xuất hiện, ai đó phải tạo ra chúng.

Chúng tôi sẽ chỉnh sửa README bằng một cam kết mới thông qua trình duyệt, do đó mô phỏng công việc song song. Như thể ai đó đã thực hiện các thay đổi trong cùng một tệp khi chúng tôi đang làm việc với nó. Kết quả sẽ là xung đột. Chúng tôi sẽ xóa từ "fully" khỏi dòng 10.

Thực hiện chức năng của chúng tôi

Nhiệm vụ của chúng ta là thay đổi README và thêm mô tả cho bài viết mới. Nghĩa là, công việc trong Git đi qua IntelliJ IDEA. Thêm điều này:

Các thay đổi được thực hiện. Bây giờ chúng ta có thể tạo một cam kết. Nhấn CTRL+K , điều này mang lại cho chúng tôi:

Trước khi tạo một cam kết, chúng ta cần xem xét kỹ cửa sổ này cung cấp những gì.

Trong phần Thông báo cam kết , chúng tôi viết văn bản liên quan đến cam kết. Sau đó, để tạo nó, chúng ta cần nhấp vào Cam kết .

Chúng tôi viết rằng README đã thay đổi và tạo cam kết. Một cảnh báo bật lên ở góc dưới bên trái với tên của cam kết:

Kiểm tra xem nhánh chính có thay đổi không

Chúng tôi đã hoàn thành nhiệm vụ của mình. Nó hoạt động. Chúng tôi đã viết bài kiểm tra. Mọi thứ đều ổn. Nhưng trước khi đẩy lên máy chủ, chúng ta vẫn cần kiểm tra xem có bất kỳ thay đổi nào trong nhánh chính trong thời gian chờ đợi hay không. Làm thế nào điều đó có thể xảy ra? Khá dễ dàng: ai đó nhận nhiệm vụ sau bạn và ai đó hoàn thành nhiệm vụ đó nhanh hơn bạn hoàn thành nhiệm vụ của mình.

Vì vậy, chúng ta cần phải đi đến chi nhánh chính. Để làm điều này, chúng ta cần thực hiện những gì được hiển thị ở góc dưới bên phải trong ảnh chụp màn hình bên dưới:

Trong nhánh chính, nhấn CTRL+T để nhận các thay đổi mới nhất từ ​​máy chủ từ xa. Nhìn vào những thay đổi, bạn có thể dễ dàng thấy điều gì đã xảy ra:

Từ "fully" đã bị xóa. Có thể ai đó từ bộ phận tiếp thị đã quyết định rằng nó không nên được viết như vậy và giao cho các nhà phát triển nhiệm vụ cập nhật nó.

Bây giờ chúng tôi có một bản sao cục bộ của phiên bản mới nhất của nhánh chính. Quay trở lại readme-improver .

Bây giờ chúng ta cần khởi động lại các thay đổi từ nhánh chính sang nhánh của chúng ta. Chúng tôi làm điều này:

Nếu bạn đã làm đúng mọi thứ và làm theo tôi, kết quả sẽ hiển thị xung đột trong tệp README:

Ở đây chúng tôi cũng có rất nhiều thông tin để hiểu và tiếp thu. Hiển thị ở đây là danh sách các tệp (trong trường hợp của chúng tôi là một tệp) có xung đột. Chúng ta có thể chọn từ ba tùy chọn:

  1. chấp nhận của bạn — chỉ chấp nhận những thay đổi từ readme-improver.
  2. chấp nhận của họ - chỉ chấp nhận những thay đổi từ chủ.
  3. hợp nhất — tự chọn những gì bạn muốn giữ lại và những gì cần loại bỏ.

Không rõ những gì đã thay đổi. Nếu có những thay đổi là nhánh chính, thì chúng phải cần thiết ở đó, vì vậy chúng tôi không thể đơn giản chấp nhận những thay đổi của mình. Theo đó, chúng tôi chọn hợp nhất :

Ở đây chúng ta có thể thấy rằng có ba phần:

  1. Đây là những thay đổi từ readme-improver.
  2. Kết quả hợp nhất. Hiện tại, đó là những gì đã tồn tại trước khi có những thay đổi.
  3. Những thay đổi từ nhánh chính.

Chúng tôi cần tạo ra một kết quả hợp nhất sẽ làm hài lòng tất cả mọi người. Xem lại những gì đã được thay đổi TRƯỚC những thay đổi của chúng tôi, chúng tôi nhận ra rằng họ chỉ cần xóa từ "fully". Ổn không có vấn đề! Điều đó có nghĩa là chúng tôi cũng sẽ xóa nó trong kết quả đã hợp nhất và sau đó thêm các thay đổi của chúng tôi. Khi chúng tôi sửa kết quả đã hợp nhất, chúng tôi có thể nhấp vào Áp dụng .

Sau đó, một thông báo sẽ bật lên, cho chúng tôi biết rằng cuộc nổi loạn đã thành công:

Ở đó! Chúng tôi đã giải quyết xung đột đầu tiên của mình thông qua IntelliJ IDEA.

Đẩy các thay đổi đến máy chủ từ xa

Bước tiếp theo là đẩy các thay đổi đến máy chủ từ xa và tạo yêu cầu kéo. Để làm điều này, chỉ cần nhấn CTRL+SHIFT+K . Sau đó, chúng tôi nhận được:

Ở bên trái, sẽ có một danh sách các xác nhận chưa được đẩy vào kho lưu trữ từ xa. Bên phải sẽ là tất cả các tệp đã thay đổi. Và thế là xong! Nhấn Push và bạn sẽ cảm thấy hạnh phúc :)

Nếu đẩy thành công, bạn sẽ thấy một thông báo như thế này ở góc dưới bên phải:

Phần thưởng: tạo yêu cầu kéo

Hãy truy cập kho lưu trữ GitHub và chúng tôi thấy rằng GitHub đã biết những gì chúng tôi muốn:

Nhấp vào So sánh & kéo yêu cầu . Sau đó nhấp vào Tạo yêu cầu kéo . Vì chúng ta đã giải quyết mâu thuẫn từ trước nên bây giờ khi tạo pull request, chúng ta có thể merge nó ngay lập tức:

Đó là nó cho bây giờ!