Bagaimana cara membuat cabang "root" baru (dan kosong!)?

135

Saya ingin mendefinisikan cabang "root" baru di repositori git ini. Cabang "root" yang saya maksud adalah cabang yang sepenuhnya independen dari semua cabang lain dalam repositori 1 .

Sayangnya, bahkan komit (sebut saja A) di bagian paling bawah dari pohon komit repo berisi banyak file (ini adalah repositori yang diinisialisasi pada proyek yang sudah cukup matang).

Ini berarti bahwa meskipun saya berikan Asebagai cabang baru <start-point>, cabang baru ini tidak akan mulai dari "sabak bersih", tetapi itu akan berisi semua file yang dilakukan A.

Apakah ada cara saya bisa membuat cabang yang benar-benar telanjang di repositori ini, dengan <start-point>sedekat Amungkin?


1 BTW, ini tidak setara dengan membuat repo baru. Repo yang terpisah akan kurang nyaman karena banyak alasan.


EDIT : OK, ini yang saya lakukan, berdasarkan jawaban vcsjones :

# save rev of the current earliest commit
OLDBASE=$(git rev-list --max-parents=0 HEAD)

# create a new orphan branch and switch to it
git checkout --orphan newbranch
# make sure it's empty
git rm -rf .

# create a new empty commit in the new branch, and
# save its rev in NEWBASE
git commit --allow-empty -m 'base commit (empty)'
NEWBASE=$(git rev-list HEAD)

# specify $NEWBASE as the new parent for $OLDBASE, and
# run filter-branch on the original branch
echo "$OLDBASE $NEWBASE" > .git/info/grafts
git checkout master
git filter-branch

# NOTE: this assumes that the original repo had only one
# branch; if not, a git-filter-branch -f <branch> command
# need to be run for each additional branch.

rm .git/info/grafts

Meskipun prosedur ini sedikit terlibat, hasil akhirnya adalah komit dasar kosong yang dapat berfungsi sebagai <start-point>untuk "cabang bersih-batu tulis" baru apa pun; yang perlu saya lakukan adalah

git checkout -b cleanslate $(git rev-list --max-parents=0 HEAD)

Di masa depan saya akan selalu membuat repositori baru seperti ini:

git init
git commit --allow-empty -m 'base commit (empty)'

... sehingga komit pertama kosong , dan selalu tersedia untuk memulai cabang independen baru. (Ini akan, saya tahu, fasilitas yang sangat jarang dibutuhkan, tetapi cukup mudah untuk membuatnya tersedia.)

kjo
sumber
1
@Anonimoose: Hanya sebagai catatan (daripada debat): Saya tidak setuju dengan pendapat Anda.
kjo
1
Tampaknya ada solusi yang lebih sederhana berdasarkan git rebase --onto, lihat stackoverflow.com/questions/645450/…
Stéphane Gourichon

Jawaban:

223

Gunakan --orphansaat membuat cabang:

git checkout --orphan YourBranchName

Ini akan membuat cabang baru dengan nol komit di atasnya, namun semua file Anda akan dipentaskan. Pada titik itu Anda bisa menghapusnya.
("hapus mereka": A git reset --hardakan mengosongkan indeks, meninggalkan Anda dengan pohon kerja kosong)

Lihatlah halaman manual untuk checkout untuk informasi lebih lanjut tentang --orphan.

vcsjones
sumber
Apakah ini pada dasarnya membuat batu tulis kosong? Seperti dalam, dari awal? Atau apakah itu menyimpan semua perubahan Anda sebelumnya, tetapi tidak dalam sejarah git?
Con Antonakos
4
@ConAntonakos Ini membuat cabang baru tanpa orang tua. Cabang-cabang lain tidak terpengaruh, semua perubahannya disimpan.
fuz
11

Untuk menambah jawaban yang diterima - praktik terbaik untuk kembali ke keadaan bersih adalah dengan membuat komit kosong awal sehingga Anda dapat dengan mudah rebase saat menyiapkan cabang untuk anak cucu. Plus karena Anda menginginkan kondisi bersih, Anda mungkin telah melakukan file yang tidak seharusnya, jadi Anda harus menghapusnya dari indeks. Dengan mengingat hal-hal tersebut, Anda harus:

$ git checkout --orphan dev2
Switched to a new branch 'dev2'
$ git reset # unstage all the files, you probably don't want to commit all of them
$ git commit --allow-empty -m 'Initial empty commit'
[dev2 (root-commit) a515c28] Initial empty commit
Mr_and_Mrs_D
sumber
1
Saya percaya ini tidak perlu pada 2012 karena Anda dapat rebase ke root .
Timmmm
1

Jika Anda menggunakan git 2.23 atau lebih tinggi, Anda mungkin terbiasa git switch dangit restore bukannya menggunakan git checkout. Jika demikian, benderanya sama dengan yang disebutkan dalam jawaban ini .

git switch --orphan YourBranchHere
Kapten Man
sumber
1

Apakah ada cara saya bisa membuat cabang yang benar-benar telanjang di repositori ini.

Perintah aktual untuk menggunakan (dengan Git 2.28+) adalah:

git switch --discard-changes --orphan newBranch
# or
git switch -f --orphan newBranch

git switchtersedia dari Git 2.23 (Agustus 2019), dan menggantikan membingungkan tua git checkoutperintah .

Tetapi saya akan merekomendasikan Git 2.28 (Q3 2020), karena git switch --discard-changes --orphan telah dioptimalkan dalam versi itu.

Lihat komit 8d3e33d , komit 8186128 (21 Mei 2020) oleh brian m. carlson ( bk2204) .
(Digabung oleh Junio ​​C Hamano - gitster- dalam commit ded44af , 09 Jun 2020)

builtin/checkout: menyederhanakan inisialisasi metadata

Ditandatangani oleh: brian m. carlson
Diulas oleh: Derrick Stolee

Ketika kita sebut init_checkout_metadatadi reset_tree,kita ingin lulus ID objek komit yang bersangkutan sehingga dapat dikirimkan ke filter, atau jika tidak ada komit, pohon.

Kami mengantisipasi kasus terakhir ini, yang dapat terjadi di tempat lain dalam kode checkout, tetapi tidak dapat terjadi di sini.

Satu-satunya kasus di mana kita tidak memiliki komit objek adalah ketika memohon git switchdengan --orphan.

Selain itu, kami hanya dapat menekan jalur kode ini tanpa objek komit tambahan dengan salah satu --forceatau --discard-changes.

Dalam kasus seperti itu, tidak ada gunanya menginisialisasi metadata checkout dengan komit atau pohon karena

  • (a) tidak ada komit, hanya pohon yang kosong, dan
  • (B) kami tidak akan pernah menggunakan data, karena tidak ada file akan tercoreng ketika memeriksa cabang tanpa file.

Berikan ID objek semua-nol dalam kasus ini, karena kita hanya perlu beberapa nilai yang merupakan pointer yang valid.

Uji:

git switch master
echo foo >foo.txt
git switch --discard-changes --orphan new-orphan2
git ls-files >tracked-files
# test_must_be_empty tracked-files
VONC
sumber