簡體   English   中英

如何使用 Git 命令將多個單獨的文件夾添加到 GitHub,以便每個文件夾可以單獨更新

[英]How to use Git commands to add multiple separate folders to GitHub such that each folder can be updated seperately

所以我對整個 GitHub 和 Git 都是新手。 我最近學習了 Git 的基礎知識(添加、推送、拉取、克隆等)。 我對 Java 教授的介紹要求我為我所有的課堂作業創建一個 git hub 存儲庫。 她告訴我以這樣的方式組織它,每個作業都有單獨的文件夾,每個作業文件夾包含多個源文件。

所以我像這樣設置我的文件:Java(主文件夾)-> Hw1 + Hw2 + Hw3 等。我將如何使用 git 來做到這一點? 所有這些文件夾都應該在我的本地和 git hub 存儲庫中,我應該能夠單獨對它們進行更改。

先感謝您。 我被困住了。

讓我們從一些基礎知識開始。 您已經了解您的計算機使用樹形結構的文件系統:也就是說,一個目錄(或文件夾——這些術語現在可以互換)包含文件和/或更多目錄/文件夾,而這些目錄/文件夾又包含更多文件和/或文件夾,等等。Windows 原生使用反斜杠\來分隔各個組件,這樣您可能會擁有:

java\hw1\main.java
java\hw1\sub.java
java\hw2\main.java

等等。 Windows可以使用正斜杠(某些命令可能將它們用於其他目的,但它們確實適用於文件名),並且所有非 Windows 操作系統都傾向於使用正斜杠,這樣更易​​於鍵入。 Git 也使用正斜杠,所以這就是我將在這里做的。

(除此之外:Windows 和 macOS 默認使用“不區分大小寫但保留大小寫”規則,因此,如果您創建一個名為readme.txt的文件,您可以稍后使用名稱ReadMe.txtREADME.TXT打開它,但它仍然命名為全小寫。相比之下,Git 通常區分大小寫,並認為readme.txtReadMe.txtREADME.TXT三個不同的文件名。這在這些系統上造成了無盡的悲痛1有時甚至是最好的,或者在最簡單,避免所有問題的方法是在任何地方完全避免大寫字母。在某種程度上,你可以使用java代替Javahw1代替Hw1等等,我鼓勵你這樣做。)

當您要求 Git 使用git init創建一個新的空存儲庫時, 2 Git 創建一個名為.git的隱藏文件夾。 這個隱藏文件夾將包含 Git 的所有文件:在這里,Git 將存儲其主要的兩個數據庫。 我們稍后會討論這些。 Git 創建.git地方是你當前的工作目錄,所以如果你在java/hw1並運行git init ,Git 會創建java/hw1/.git 如果您在java中並運行git init ,Git 會創建java/.git

請注意, java/.gitjava/hw1/.git是不同的文件夾路徑名,因此您可以創建兩個存儲庫。 你不想這樣做,但這就是你所做的。 (我基於此評論提出此主張。)我們將很快回到“如何解決此問題”。


1特別是,使用 Linux 的人可以從字面上創建三個不同的文件,它們只是大小寫不同,將所有三個文件都放入 Git 存儲庫中的一個提交中,當您在 Windows 系統上檢查此提交時會給您留下一個問題。 如果您習慣於從小寫輸入到匹配大小寫的系統映射,並且您要求編輯器在 Linux 上創建java/hw1/thing.java ,它實際上可能會在您現有的旁邊創建一個javahw1 JavaHw1 由於這些是不同的目錄,它們可以存儲與Java/Hw1/中的名稱完全相同的不同文件,包括名稱大小寫。 Git 會愉快地存儲所有這些文件,而 Windows 通常無法正確提取此類提交。

2請注意, git init將首先檢查您是否已經在某個現有存儲庫中。 在這種情況下,Git 不會創建新的存儲庫,而是“重新初始化”現有的存儲庫。 在大多數情況下,像這樣“重新初始化”根本沒有效果。


關於 Git 和 Git 存儲庫的主要知識

Git 存儲庫——或者我有時稱之為存儲庫本身——主要由兩個數據庫組成。 一個通常要大得多。 它包含提交和其他支持 Git 對象。 這些對象都具有 Git必須具有哈希 ID (或更正式地說,對象 IDOID )才能從數據庫中檢索對象。 這可能會迫使人類記住 Git 提交哈希 ID,但這是一個糟糕的計划:哈希 ID 非常大,看起來非常隨機,而且人類一般無法記住。

出於這個原因,Git 存儲庫包含第二個,通常要小得多的數據庫。 在這個數據庫中,Git 存儲名稱:分支名稱、標簽名稱、遠程跟蹤名稱以及許多其他類型的名稱。 這些名稱供(和其他人)使用。 每個名稱都存儲一個哈希 ID,但這足以使一切正常工作。 因此,您將使用分支名稱,例如mainmaster 此名稱包含最新提交的哈希 ID,它允許 Git 檢索該提交。

每個提交存儲兩件事:

  • 提交存儲了您或任何人進行該提交時每個文件(即 Git 知道的)的完整快照 提交中的文件以一種特殊的、只讀的、僅限 Git 的、壓縮和去重的形式存儲,只有 Git 可以讀取,實際上沒有任何東西可以寫入。 (這使用了我提到的一些“支持對象”;這些文件實際上作為“Git 對象”存儲在對象數據庫中。)因為只有 Git 可以使用這些文件,所以提交中的文件本身是無用的。 稍后我們將看到我們如何處理這些文件。

  • 同時,存儲快照的同一個提交也存儲了一些元數據,或者關於提交本身的信息:誰做了它(你,可能),以及什么時候,例如。 為了使“分支”——Git 中一個定義不明確的詞(請參閱“分支”到底是什么意思? )——工作,提交的元數據包含先前提交的哈希 ID。

這個“包含先前提交的哈希 ID”是 Git 存儲歷史記錄的方式:分支名稱,例如main ,讓 Git 找到您所做的最后一次提交,然后通過讀取該提交,Git 可以找到第二個提交的哈希 ID。最后一次提交。 例如,假設最后一次提交的哈希 ID 是H (它實際上是一個很大的丑陋的十六進制數字,所以我們只是用H來代替它)。 然后我們說名稱main指向提交H 但是提交H包含一個較早的或提交的哈希 ID:我們稱它為G 我們說H指向G ,我們可以得出:

        <-G <-H   <--main

由於G一個提交,它也有這些指向指針之一。 通過讀取提交G的元數據,Git 可以找到其父級的原始哈希 ID; 讓我們稱之為提交F

... <-F <-G <-H   <--main

所以main指向H ,它指向G ,它指向F ,它指向……嗯,這一直持續到我們回到第一個提交——也許提交A ——這是第一個,不能向后指向,因此根本沒有。

這意味着每個提交不是一個哈希 ID,而是在其元數據中存儲一個先前提交的哈希 ID列表 該列表可以為空,並且用於第一次提交。 它也可以有多個哈希 ID,但我們不會在這里討論這種情況。 大多數存儲庫中的大多數提交都是“普通”提交,並且只有一個父提交。

你的“工作樹”

然后,存儲存儲名稱——例如分支名稱——幫助 Git 為我們找到提交(我們只需要記住分支名稱),存儲提交然后存儲文件 但是提交的內容(連同實際提交本身)都是完全只讀的。 Git 必須這樣做才能使散列方案起作用。 如果我們不能在它們上寫,存儲的文件有什么用? 而且,只有Git可以讀取它們,如果我們連它們都無法讀取它們有什么用呢?

這就是你的工作樹的用武之地。大多數 Git 存儲庫都有一個工作樹。 3存儲庫的工作樹很簡單,就是您工作的地方 而且,正如我們之前看到的,如果您在某個目錄中使用git init創建一個新的、完全空的存儲庫,然后進行初始提交: 4

mkdir new
cd new
echo example > README.txt
git init
git add README.txt
git commit

您將在我們剛剛創建的new/文件夾( mkdir new )並輸入( cd new )中找到一個隱藏的.git文件夾。 這個 Git 存儲庫在new/.git中的工作樹new/ ,我們在該工作目錄中創建的文件README.txt現在存儲在該存儲庫的第一個(也是迄今為止唯一的)提交

如果我們現在修改一個文件,和/或添加一個新文件,並適當地使用git addgit commit ,我們將獲得第二個提交,它存儲(永遠5 )該文件的新版本。 第二個提交具有作為其父提交的第一個提交,它(永遠)存儲只有一個文件的早期版本。

第二次提交現在是我們當前的提交,並且現在是主分支或主分支上的最后一次提交(無論它的名稱是什么)。

Git 允許我們檢查我們存儲在存儲庫中的任何提交。 當我們這樣做時,Git將從我們的工作樹中刪除當前提交相關的文件。 相反,它將與新選擇的提交一起安裝到我們的工作樹中 - 然后成為當前提交。

通過這種方式,我們可以在任何時候“回到過去”,到任何舊版本,作為提交存儲在大數據庫中。 我們所要做的就是找到它的提交哈希 ID(例如git log就派上用場了)。 不過,這不是我們現在要關注的。


3這里的例外是所謂的存儲庫。 我們不會在這里介紹這些。

4這些是 Unix-shell 風格的命令,因為我自己不使用 Windows,但這應該在 git-bash 中工作,它只是Windows 的一個端口,用於與 Git 一起使用。 您可以在 PowerShell 甚至CMD.EXE中執行所有這些操作,但某些命令詳細信息可能會更改。

5好吧,永遠,或者只要提交本身繼續存在。 如果我們刪除提交,我們會刪除它的快照。 這實際上是很難做到的! 但是,如果我們適當地刪除存儲庫,我們會破壞兩個數據庫,這會刪除所有提交,這很容易做到。


“嵌套”存儲庫:您不想要但制作的東西

鑒於計算機——宿主操作系統,在你的例子中是 Windows,但 macOS 和 Linux 也是如此——需要並使用樹形結構的文件系統,我們可以設置這樣的結構:

java
  .git
    <various Git repository control files and databases>
  hw1
    .git
      <various Git repository control files and databases>
    main.java
  hw2
    .git
      <various Git repository control files and databases>
    main.java

等等。 這里我們每個hw目錄有一個存儲庫,加上java目錄中的一個整體包含存儲庫

但問題是:Git 實際上不能在 Git 提交中存儲 Git 存儲庫。 6 “外部”存儲庫(在本例中為java/.git中的存儲庫,其工作樹是java/*文件)不會這樣做,而是使用 Git 調用的gitlink存儲 Git 調用的子模塊 要正確存儲子模塊,您必須使用git submodule add ,而不是git add git add只創建或更新gitlink ,它是半個子模塊。

如果有人確實想要子模塊(但不想要),這個git submodule add方法就是如何制作它們。 結果是,當您克隆java存儲庫時,您會獲得文件以及神奇的 gitlinks,Git 將需要這些文件來運行其他git clone命令,每個子模塊一個。 這樣,克隆java存儲庫的人可以運行git submodule update --init來運行更多的git clone命令。 但同樣,這不是你想要的。


6如果你真的需要,有一些技巧可以解決這個問題,但一般來說這不是一個好主意。 最近的safe.directory東西是安全問題的產物,當有人發現這樣的技巧時會導致 CVE。 Git允許的技巧包括重命名.git目錄; 它不允許或過去意外允許的那些會導致 CVE。 😀


修復混亂

在這一點上我們應該做的觀察是:

  • Git存儲提交 它不存儲文件(盡管提交確實存儲文件)。 它存儲提交
  • 您想要的是具有多個提交的單個存儲庫,其中第一次提交——或者可能是第二次; 見下文——包含一個名為hw1/main.java的文件, 8但沒有名為hw2/whatever的文件。
  • 您現在擁有的是多個存儲庫:一個是超級項目,具有名為hw1hw2等的子模塊(或半子模塊),然后是更多存儲庫,這些存儲庫被克隆到hw1hw2等中,每個存儲庫都包含一個main.java和任何其他文件。

現在,如果我們假設(或您驗證)到目前為止您不需要在任何這些存儲庫中保存任何提交,我們可以做的就是刪除所有.git文件夾及其內容

也就是說,在類似 Unix 的 shell 上,我們將運行:

cd java
ls               # make sure we're in the right place
rm -rf .git      # remove this working tree's Git repository
rm -rf hw1/.git  # remove the Git repository in hw1/
rm -rf hw2/.git  # and so on ...

請注意,我們在隱藏的 Git 文件夾上使用操作系統的remove命令,並帶有“不詢問就刪除所有內容”選項。 Git沒有機會阻止我們:我們在這里完全繞過了 Git。 Git 的所有文件,包括兩個大型數據庫,都被完全刪除。 這可能是不可恢復的(取決於您的操作系統以及您是否使用操作系統的“不可恢復刪除”命令,或者它的“移動到垃圾箱,以便在我改變主意時將其取回”命令,還取決於是否您有良好的備份,例如 macOS Time Machine)。

我們現在只有所有的工作樹,沒有.git文件夾:沒有剩下的存儲庫 但是所有文件仍然存在,因為簽出的文件曾經並且仍然存在於工作樹中。

現在我們在java目錄中創建一個新的、完全空的存儲庫,我們仍在:

git init
[Git prints message: Initialized empty Git repository in ...]

我們現在有了我們最初的、完全空的存儲庫。 我喜歡創建一個只包含一個README.txt的第一個提交(可能還有一個或兩個類似的文件):

echo repository for "insert class name here" > README.txt
git add README.txt
git commit -m "Initial commit"

我們現在准備“完成”家庭作業 #1:

git add hw1
git commit
(write a good, proper commit message in editor)

通過在 hw1中沒有 Git 存儲庫hw1運行git add hw1 ,我們添加了hw1的所有文件(包括hw1中任何子目錄中的任何文件)。

git commit命令提交到目前為止存儲的內容,我們的git add更新。 因此,當我們提交添加hw1時,我們會得到README.txt ——我們沒有更改它,所以這個提交實際上重新使用了文件的先前版本——加上所有hw1/*文件。

我們現在可以使用git add hw2和 committing 等“完成”家庭作業 #2。 我們最終在java/.git目錄中獲得了一個存儲庫,其中包含多個提交:一個包含README文件的初始提交,以及添加了每個作業分配的后續提交。 只有一個分支名稱,它保存最后一次提交的哈希 ID。

將其推送到 GitHub

您的最后一個問題是,如果您已經創建了一個 GitHub 存儲庫並在其中放入了一些提交,那么您現有的 GitHub 存儲庫將不願意丟失這些提交。 你有幾個選擇:

  • 如果您真的願意,您可以保留這些提交。
  • 您可以告訴 GitHub 完全刪除該存儲庫,然后創建一個具有相同名稱的新存儲庫。
  • 或者,您可以在具有新存儲庫的筆記本電腦(或其他計算機)上使用git push --force命令GitHub 上的 Git 軟件繼續執行並丟失舊存儲庫中的舊提交。

這里的一般想法是,使用最后一個選項,我們(和 Git)從某個分支名稱(如mastermain )開始查找提交。 這給了我們最后一次提交的哈希 ID,從那里,我們讓 Git 向后工作。

假設我們命令(而不僅僅是詢問)某個 GitHub 存儲庫來獲取的提交鏈。 也就是說,他們有:

A <-B <-C   <--main

我們現在創建一個全新的(空)存儲庫,並放入兩個提交:一個初始提交D和第二個提交E ,它們都沒有與原始存儲庫中這三個提交中的任何一個相同的哈希 ID:

D <-E   <--main

我們運行git remote add origin url進行設置,以便我們可以git push到 GitHub。 如果我們運行:

git push origin main

我們的 Git 會將提交DE發送到 GitHub,然后禮貌地詢問他們是否可以提交DE添加到他們的存儲庫中。 但這會給他們:

A <-B <-C

D <-E   <-- main

他們注意到,這意味着他們不再有任何名稱可以用來查找提交C ,這意味着他們將“丟失”所有三個哈希 ID。 所以他們會說不 如果我這樣做,我將失去對某些提交的訪問權限!

您的 Git 軟件將此報告為! [rejected] main -> main (non-fast-forward) ! [rejected] main -> main (non-fast-forward) :這意味着他們說他們可能會丟失提交。 但這正是您想要的:您希望他們失去ABC 那些提交不好! 所以你可以使用git push --force origin main ,它再次發送DE但這次命令他們將他們的main點指向E

你必須擁有權限——GitHub 添加了基礎 Git 無法提供的一整套權限——但如果你擁有這個 GitHub 存儲庫,你可能已經擁有了正確的權限。 9所以他們會服從:他們會讓他們的分支名稱main指向提交E ,而“忘記”提交ABC 10


8請注意,雖然您的操作系統需要包含子文件夾和文件的文件夾,但Git只存儲“帶有斜杠的長名稱的文件”。 Git 了解您的操作系統對文件夾的要求,並且可以將hw1/main.java轉換為“文件夾main.java中的文件hw1 。它會自動保存操作系統的hw1/main.java ——一個名為main.java的文件在文件夾中命名為hw1 — 作為名為hw1/main.java的 Git文件

通常,您無需擔心整個混亂。 不得不擔心它的時候是你想在 Git 中存儲一個空文件夾,因為 Git 確實無法做到這一點。 Git 只存儲文件。 不過有一些技巧:請參閱如何將空白目錄添加到 Git 存儲庫? .

9如果您擁有存儲庫,那么您沒有權限的唯一方法是您登錄 GitHub 並告訴他們拒絕您自己的權限。 要解決此問題,請再次登錄 GitHub 並告訴他們將權限還給您自己。

10 個“正常”的 Git 設置確實最終會以這種方式忘記(或丟失)提交。 然而,GitHub 將他們的軟件設置為永久保留所有提交。 因此,如果您GitHub 發送了錯誤的提交,並且無論出於何種原因,您確實需要將其刪除,您必須聯系 GitHub 支持並讓他們將其從系統中清除。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM